Skip to content

Instantly share code, notes, and snippets.

@HelloZaWarudo
Last active November 1, 2023 05:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HelloZaWarudo/45d195b2768d1bafef72884ec522d158 to your computer and use it in GitHub Desktop.
Save HelloZaWarudo/45d195b2768d1bafef72884ec522d158 to your computer and use it in GitHub Desktop.
/*
Step 1: Prove that the winning solution auctioneer submitted is correct.
Step 2: Verify the reciept is the one aunctioneer sent to the solver
Step 3: Compare winning solution and solver's solution
*/
//This file is generated by the AxiomREPL. DO NOT DIRECTLY EDIT THIS FILE!
//To make changes, go to https://repl.axiom.xyz/ and export a new circuit.
//
// _ _____ ______ _____ _
// /\ (_) | __ \| ____| __ \| |
// / \ __ ___ ___ _ __ ___ | |__) | |__ | |__) | |
// / /\ \ \ \/ / |/ _ \| '_ ` _ \| _ /| __| | ___/| |
// / ____ \ > <| | (_) | | | | | | | \ \| |____| | | |____
// /_/ \_\/_/\_\_|\___/|_| |_| |_|_| \_\______|_| |______|
//
//
// Some constants
const zero = BigInt(0);
const one = BigInt(1);
// ---------------------------Clarification of inputs-------------------------------------
// Below input should be read inside the circuit:
/*
"published_auction_id": 1
--auction id the challenger is challenging, if we use challenge_auction_id that challenger provides,
--then this paramater is redundant.
--(not sure if using this id to find corresponding storage is convinient, of course for the presentation,
--we can choose whatever way that is convinient)
"published_sell": "0x8f0A561075aA46833c5519001b7579E58EC825C9",
--In this auction, the currency to sell, which should be same as token0 based on today's conversation
"published_amount": 1000,
--In this auction, the amount of currency (published_sell) want to sell
"published_buy": "0x8f0A561075aA46833c5519001b7579E58EC825C9",
--In this auction, the currency to buy, which should be same as token1 based on today's conversation
"published_task_signature": "",
--In this auction, the signature of the task,
--i.e. published_task_signature = SIG_{auctioneer}(published_auction_id, published_sell, published_amount, published_buy)
--Again, if we cannot find easy way to verify signature using current Axiom, we can check it in smart contract (EVM).
"published_winning_value": 2131312312321321,
--The published winning value (amount of currency bought in the winning solution, given the uni-swap pools' states at the time that auction happened)
*/
// Below input are real input to the circuit:
/*
"challenge_auction_id": 1,
"challenge_sell": "0x8f0A561075aA46833c5519001b7579E58EC825C9",
"challenge_amount": 1000,
"challenge_buy": "0x8f0A561075aA46833c5519001b7579E58EC825C9",
"challenge_task_signature": "",
"challenge_value": 2131312312321322,
--above 6 terms are similar as above, only difference is these are provided by the challenger,
--they are inputs of the circuit instead of read inside the circuit
--and be aware that challenge_task_signature is also signed by auctioneer at the time he publish task
--to solvers, we need this here to show that the challenger doesn't make up fake task
"challenge_solution": "",
--this is complete chllenger's solution. Based on today's meeting, we can simplify the solution
--involves only 1 exchange in 1 uniswap pool. Then this can just be 1 contract_address.
--However, it is ok to leave it here since we are not going to check challenger's complete solution in the
--challenge() method. The verification is done by the auctioneer before he sent solver the receipt,
--in challenge() method, we verify chllenger's soluton only by verify the signature signed by auctioneer
--in the receipt.
"challenge_signature": "",
--This is SIG_{solver/chllenger}(all above 7 paramaters, i.e. challenge_auction_id, ..., challenge_solution)
--This is signed by challenger
--again, we can check this outside the circuit but in smart contract/ EVM
"challenge_receipt": ""
--This is SIG_{auctioneer}(all above 8 paramaters, i.e. challenge_auction_id, ..., challenge_signature)
--This is signed by auctioneer
--again, we can check this outside the circuit but in smart contract/ EVM
*/
// parameters published_sell, published_buy and token0, token1 are same
// Changed some codes in line 152-170, for this part, I think it is better to just check if the auctioneer's
// published winning value is valid or not. And comparison of winning value and challenge value is
// is in the last step (line 199 - 204). Since if auctioneer published fake values, we may want to splash auctioneer directly.
// Checked Uni-swap V2 amount out method, function checkUniswapV2Exec() looks good to me. I only changed
// inputs and output (line 167)
/*
---------------------part we need to do-------------------------
1. read parameters (line 2-14 in the input) from smart contract given challenge_auction_id
(if using id to loop up is convinient, if not we may want challenger provides block number and we can
use block number to read?)
2. check following signatures in the smart contract:
a. signature published_task_signature, if this is wrong, challenge succeeds
b. challenge_task_signature, if this is wrong, challenge fail
c. challenge_receipt, if wrong, challenge fail
d. challenge_signature, if challenge_receipt is correct, then if this is wrong means auctioneer
cheated, so if challenge_receipt is correcnt, and challenge_signature is wrong, then challenge succeeds
3. check age in smart contract
4. output of the circuit when challenge success / challenge fail(call back functions?).
*/
//--------------------------------------------------------------------------------------------------
// Step 1: count block age, if > 3 days, challenge fail
// Q1 : Do it in EVM?
//--------------------------------------------------------------------------------------------------
// Step 2: verify auctioneer published legal winning solution
// substep 2.0: read the winning solution [Ex1,Ex2, …], make sure they are in valid form
// Q2 : want to read from smart contract's storage instead of inputs to the circuit?
checkEqual(witness(winning_contract_address.length), numSolutions);
checkEqual(witness(token0.length), numSolutions);
checkEqual(witness(token1.length), numSolutions);
checkEqual(witness(block.length), numSolutions);
// substep 2.1: follow [Ex1, Ex2, ..], read history data of amounts of currency of each pool
// store them in a map
// update value, and check for each exchange Exi, we have enough amount of related selling currency
const map = new Map();
// Q3 : same, read from uniswap pool history balance
// for(var i = 0; i < numSolutions.value(); i++){
// let pool = getAccount(winning_contract_address[i], block[i]);
// }
for(var i = 0; i < numSolutions.value(); i++){
// let pool = getAccount(winning_contract_address[i], block[i]);
// extract value of tokens prices from the pool of uinswap v2
const storage = getStorage(block[i], winning_contract_address[i]);
// log(storage);
// gets the value of the specified slot in the contract's storage
// const slotValueToken0Reserve = storage.slot(constant(5));
// const slotValueToken1Reserve = storage.slot(constant(6));
// checkEqual(token0Reserve[i], slotValueToken0Reserve.toCircuitValue());
// checkEqual(token1Reserve[i], slotValueToken1Reserve.toCircuitValue());
checkUniswapV2Exec(published_winning_value, token0Reserve[i], token1Reserve[i], published_amount);
}
function checkUniswapV2Exec(publishedAmountOut, reserveIn, reserveOut, token0in){
//code from uniV2 https://github.com/Uniswap/v2-periphery/blob/master/contracts/libraries/UniswapV2Library.sol#L43
// uint amountInWithFee = amountIn.mul(997);
// uint numerator = amountInWithFee.mul(reserveOut);
// uint denominator = reserveIn.mul(1000).add(amountInWithFee);
// amountOut = numerator / denominator;
const amountInWithFee = mul(token0in, constant(997));
log(amountInWithFee);
const numerator = mul(amountInWithFee, reserveOut);
const denominator = add(mul(constant(1000), reserveIn), amountInWithFee);
const amountOut = div(numerator, denominator);
// checkEqual(amountOut, challengeAmountOut);
if(isLessThan(publishedAmountOut, amountOut).value() === one) {
// challenge success
}
}
// substep 2.2: follow Ex1, Ex2, …, verify they are legal and also update amounts of currencies in pools
// substep 2.3: the final amount of C1 is no smaller than the published winning value Vw.
//--------------------------------------------------------------------------------------------------
// Step 3: verify the challenged task by comparing to the published one
// verify challenger's solution by verifying the receipt he provides
// signature verification part is currently in EVM, waiting for Axiom's ecrecover of signature verification
let isSameId = isEqual(published_auction_id, challenge_auction_id).value();
let isSameSell = isEqual(published_sell, challenge_sell).value();
let isSameBuy = isEqual(published_buy, challenge_buy).value();
let isSameAmount = isEqual(published_amount, challenge_amount).value();
let isSameSignature = isEqual(published_task_signature, challenge_task_signature).value();
if ((isSameId == zero) || (isSameSell == zero) || (isSameBuy == zero) || (isSameAmount == zero)
|| (isSameSignature == zero)) {
// challenge fail
}
//--------------------------------------------------------------------------------------------------
// Step 4: compare winning value and challenger's value
let challenge_success = isLessThan(published_winning_value, challenge_value).value();
if (challenge_success == one) {
// challenge success, splash auctioneer
} else {
// challenge fail
}
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
/*
// 0. read the solution [Ex1,Ex2, …], make sure they are in valid form
checkEqual(witness(winning_contract_address.length), numSolutions);
checkEqual(witness(token0.length), numSolutions);
checkEqual(witness(token1.length), numSolutions);
checkEqual(witness(block.length), numSolutions);
// for(var i=0; i< winning_sol.length; i++){
// let isContractAddress = ("key" in winning_sol[i]) ? 1 : 0;
// checkEqual(constant(1), constant(isContractAddress));
// }
// 1. read history data of amounts of currency of each pool in the solution
const map
for(var i=0; i < numSolutions.value(); i++){
let pool = getAccount(winning_contract_address[i], block[i]);
}
// 2. follow Ex1, Ex2, …, verify they are legal and also update amounts of currencies in pools
// 3. the final amount of C1 is no smaller than the published winning value Vw
*/
{
"winning_contract_address": ["0x3041CbD36888bECc7bbCBc0045E3B1f144466f5f"],
"token0": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"],
"token1": ["0xdAC17F958D2ee523a2206206994597C13D831ec7"],
"token0Reserve": [321312312],
"token1Reserve": [321312312],
"block": [15002251],
"numSolutions": 1,
"published_auction_id": 1,
"published_sell": "0x8f0A561075aA46833c5519001b7579E58EC825C9",
"published_amount": 1000,
"published_buy": "0x8f0A561075aA46833c5519001b7579E58EC825C9",
"published_task_signature": "",
"published_winning_value": 2131312312321321,
"challenge_auction_id": 1,
"challenge_sell": "0x8f0A561075aA46833c5519001b7579E58EC825C9",
"challenge_amount": 1000,
"challenge_buy": "0x8f0A561075aA46833c5519001b7579E58EC825C9",
"challenge_task_signature": "",
"challenge_solution": "",
"challenge_value": 2131312312321322,
"challenge_signature": "",
"challenge_receipt": ""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment