Address Contract Verified
Address
0x2992d1A31B73beE1aCBc10353872a52bE58A70ad
Balance
0 ETH
Nonce
1
Code Size
18095 bytes
Creator
0xF2d98377...4De2 at tx 0x4bddfeb7...478369
Indexed Transactions
0
Contract Bytecode
18095 bytes
0x608060405260043610610021575f3560e01c806393c717ce1461003257610028565b3661002857005b610030610062565b005b61004c60048036038101906100479190613383565b6101a0565b60405161005991906134bf565b60405180910390f35b5f61006b610271565b90508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146100db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100d290613539565b60405180910390fd5b5f6100e4610280565b90505f60048235019150813590505f8167ffffffffffffffff81111561010d5761010c613053565b5b6040519080825280601f01601f19166020018201604052801561013f5781602001600182028036833780820191505090505b509050816020840160208301375f805f80848060200190518101906101649190613818565b93509350935093505f60405180606001604052808481526020018381526020018681525090506101948185610290565b50505050505050505050565b6101a8612ff3565b5f303f90505f6040518060600160405280865167ffffffffffffffff8111156101d4576101d3613053565b5b6040519080825280602002602001820160405280156102025781602001602082028036833780820191505090505b50815260200186815260200185815250905061021e8187610290565b9250505f303f9050818114610268576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025f90613940565b60405180910390fd5b50509392505050565b5f61027b5f6109b7565b905090565b5f61028b60016109b7565b905090565b610298612ff3565b5f825190505f5b8181101561095f575f8482815181106102bb576102ba61395e565b5b602002602001015190505f602082901b60f81c60ff1690505f80608083161461030c5786846102e9906139b8565b945084815181106102fd576102fc61395e565b5b60200260200101519050610334565b79ffffffffffffffffffffffffffffffffffffffffffffffffffff602884901b5f1c175f1b90505b5f60208316146103795761035986848484888d6109c19095949392919063ffffffff16565b15610374578380610369906139b8565b94505050505061095a565b6107ef565b5f61038f84838b610f979092919063ffffffff16565b90506001808a604001511603610408577ffed86480430d9354d752c4b271494cf5fa2258a6e22592371c2d1c622cfd33548561ff008b6040015116178987815181106103de576103dd61395e565b5b6020026020010151865f1c84600388166040516103ff959493929190613aa4565b60405180910390a15b607f73ffffffffffffffffffffffffffffffffffffffff855f1c16101561047d575f896020015160ff865f1c16815181106104465761044561395e565b5b6020026020010151905060208101517fffffffffffffffffffffffff00000000000000000000000000000000000000008616179450505b5f600384160361050557835f1c73ffffffffffffffffffffffffffffffffffffffff16816040516104ae9190613b36565b5f60405180830381855af49150503d805f81146104e6576040519150601f19603f3d011682016040523d82523d5f602084013e6104eb565b606091505b50885f018960200182905282151515158152505050610776565b6001600384160361058f57835f1c73ffffffffffffffffffffffffffffffffffffffff16816040516105379190613b36565b5f604051808303815f865af19150503d805f8114610570576040519150601f19603f3d011682016040523d82523d5f602084013e610575565b606091505b50885f018960200182905282151515158152505050610775565b6002600384160361061857835f1c73ffffffffffffffffffffffffffffffffffffffff16816040516105c19190613b36565b5f60405180830381855afa9150503d805f81146105f9576040519150601f19603f3d011682016040523d82523d5f602084013e6105fe565b606091505b50885f018960200182905282151515158152505050610774565b600380841603610738575f808a602001518460f81c60ff16815181106106415761064061395e565b5b60200260200101519050602081511461068f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068690613bbc565b60405180910390fd5b60208101519150855f1c73ffffffffffffffffffffffffffffffffffffffff16826106d08860ff600889901b5f1c175f1b8f610f979092919063ffffffff16565b6040516106dd9190613b36565b5f6040518083038185875af1925050503d805f8114610717576040519150601f19603f3d011682016040523d82523d5f602084013e61071c565b606091505b508a5f018b602001829052821515151581525050505050610773565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161076a90613c24565b60405180910390fd5b5b5b5b6001808a6040015116036107ed577f3c1fc123751ad29540613e04a1686fae9519a501241ff3c1ca3b3d342311a5138561ff008b6040015116178987815181106107c3576107c261395e565b5b6020026020010151895f01518a602001516040516107e49493929190613c51565b60405180910390a15b505b855f01516108fc5760018089604001511603610856577f88ce42b8ff59d9473df9c087744134c169253d9c6ff786ee94b106a369bfc0568461ff008a6040015116178760200151604051610844929190613c9b565b60405180910390a150505050506109b1565b5f8660200151511115610873575f86602001519050604481019050505b5f866020015151116108ba576040518060400160405280600781526020017f556e6b6e6f776e000000000000000000000000000000000000000000000000008152506108c0565b85602001515b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f39190613d0b565b60405180910390fd5b5f604083161461092857610923605884901b87602001518a61153c9092919063ffffffff16565b610948565b610945605884901b87602001518a6116429092919063ffffffff16565b97505b8380610953906139b8565b9450505050505b61029f565b50600180856040015116036109af577f80ae80e2be1b30839508ea0fa59b88194af0e9957c7b9862b55f48d0e716b6db825f015183602001516040516109a6929190613d2b565b60405180910390a15b505b92915050565b5f815c9050919050565b5f80607f605887901b60f81c60ff1616905060018089604001511603610a25577fb88a5f6064992685c8a23b9825f8710a5da5d07eea2106113c62224f10bf425e8361ff008a60400151161787604051610a1c929190613d59565b60405180910390a15b5f8660e01c90505f8103610aa657607f8203610a4657600192505050610f8d565b610a6585605889901b60f81c60ff168b6118199092919063ffffffff16565b88602001819052505f8860200151511415885f019015159081151581525050602088602001515103610a9c57600192505050610f8d565b5f92505050610f8d565b60018103610af657610ac1858a611ad390919063ffffffff16565b88602001819052505f88602001515103610adb575f610ade565b60015b885f0190151590811515815250505f92505050610f8d565b60028103610b1c57610b17858884898d611b5490949392919063ffffffff16565b610f86565b60038103610b4257610b3d8583895f1c8c611ccd909392919063ffffffff16565b610f85565b60048103610b7257610b548986611d52565b895f018a602001829052821515151581525050505f92505050610f8d565b60058103610b9657610b9185885f1c8b611e6d9092919063ffffffff16565b610f84565b60078103610bbc57610bb78583895f1c8c6121b6909392919063ffffffff16565b610f83565b60088103610be357610bde8560ff895f1c168b6122159092919063ffffffff16565b610f82565b60098103610c0357610bfe858a61256f90919063ffffffff16565b610f81565b600a8103610d2657607f8203610c1e57600192505050610f8d565b8860200151607f865f60208110610c3857610c3761395e565b5b1a60f81b60f81c60ff161681518110610c5457610c5361395e565b5b602002602001015189602001518381518110610c7357610c7261395e565b5b60200260200101819052505f6040871614610cd7576001895f01518381518110610ca057610c9f61395e565b5b60200260200101906001811115610cba57610cb9613d80565b5b90816001811115610cce57610ccd613d80565b5b81525050610d21565b5f895f01518381518110610cee57610ced61395e565b5b60200260200101906001811115610d0857610d07613d80565b5b90816001811115610d1c57610d1b613d80565b5b815250505b610f80565b600b8103610d4857610d4385838b6125f59092919063ffffffff16565b610f7f565b600c8103610d6b57610d6585838b6127ad9092919063ffffffff16565b50610f7e565b60108103610dbe57610db982610da9607f885f60208110610d8f57610d8e61395e565b5b1a60f81b60f81c60ff16168c61295f90919063ffffffff16565b8b61297d9092919063ffffffff16565b610f7d565b601f8110610f3d575f610ddd8360208c6129b59092919063ffffffff16565b9050601f821691505f60ff60f81b875f60208110610dfe57610dfd61395e565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610e31575f801b610e61565b610e60875f60208110610e4757610e4661395e565b5b1a60f81b60f81c60ff168c612a5b90919063ffffffff16565b5b9050825f8114610ebf5760018114610eca5760028114610ed55760038114610ee05760048114610eeb5760058114610ef65760068114610f025760078114610f0d5760088114610f185760098114610f2357600a8114610f2e575f80fd5b436020840152610f35565b306020840152610f35565b336020840152610f35565b5a6020840152610f35565b476020840152610f35565b81316020840152610f35565b466020840152610f35565b346020840152610f35565b426020840152610f35565b326020840152610f35565b4160208401525b505050610f7c565b5f885f019015159081151581525050604051602001610f5b90613e01565b60405160208183030381529060405288602001819052505f92505050610f8d565b5b5b5b5b5b5b5b5b5b5b6001925050505b9695505050505050565b60605f8060605f805b60208110156111f357868160208110610fbc57610fbb61395e565b5b1a60f81b60f81c60ff16915060ff8203156111f357600180811115610fe457610fe3613d80565b5b895f0151607f841681518110610ffd57610ffc61395e565b5b6020026020010151600181111561101757611016613d80565b5b036110b9575f8960200151607f8416815181106110375761103661395e565b5b60200260200101515190505f6080841614611088576020816110599190613e15565b866110649190613e15565b95506020856110739190613e15565b94508180611080906139b8565b9250506110b3565b80866110949190613e15565b955080856110a29190613e15565b945081806110af906139b8565b9250505b506111ee565b5f608083161461119f5760fe820361110a575f8351036110f657886040516020016110e49190614054565b60405160208183030381529060405292505b8251856111039190613e15565b945061119a565b5f8960200151607f8416815181106111255761112461395e565b5b60200260200101515190505f60208261113e91906140a1565b1461117e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117590614141565b60405180910390fd5b60208161118b9190613e15565b866111969190613e15565b9550505b6111d0565b8860200151607f8316815181106111b9576111b861395e565b5b602002602001015151856111cd9190613e15565b94505b6020846111dd9190613e15565b935080806111ea906139b8565b9150505b610fa0565b506004846112019190613e15565b67ffffffffffffffff81111561121a57611219613053565b5b6040519080825280601f01601f19166020018201604052801561124c5781602001600182028036833780820191505090505b5094508660208601525f93505f5b6020811015611530578681602081106112765761127561395e565b5b1a60f81b60f81c60ff16915060ff8203156115305760018081111561129e5761129d613d80565b5b895f0151607f8416815181106112b7576112b661395e565b5b602002602001015160018111156112d1576112d0613d80565b5b036113fc575f6080831614611379575f8960200151607f8416815181106112fb576112fa61395e565b5b602002602001015151905084866024890101526113488a60200151607f85168151811061132b5761132a61395e565b5b60200260200101515f896004896113429190613e15565b85612a8c565b80856113549190613e15565b94506020866113639190613e15565b95508180611370906139b8565b925050506113f7565b5f8960200151607f8416815181106113945761139361395e565b5b60200260200101515190506113d98a60200151607f8516815181106113bc576113bb61395e565b5b60200260200101515f8960048a6113d39190613e15565b85612a8c565b81806113e4906139b8565b92505080866113f39190613e15565b9550505b61152b565b5f60808316146114da5760fe820361145d57838560248801015261143d8360208860048861142a9190613e15565b60208851611438919061415f565b612a8c565b6020835161144b919061415f565b846114569190613e15565b93506114d5565b5f8960200151607f8416815181106114785761147761395e565b5b602002602001015151905084866024890101526114c58a60200151607f8516815181106114a8576114a761395e565b5b60200260200101515f896004896114bf9190613e15565b85612a8c565b80856114d19190613e15565b9450505b61150d565b5f8960200151607f8416815181106114f5576114f461395e565b5b60200260200101519050602081015186602489010152505b60208561151a9190613e15565b94508080611527906139b8565b9150505b61125a565b50505050509392505050565b5f8260f81c60ff16905060ff8103611554575061163d565b5f602083516115639190613e15565b67ffffffffffffffff81111561157c5761157b613053565b5b6040519080825280601f01601f1916602001820160405280156115ae5781602001600182028036833780820191505090505b508560200151607f8416815181106115c9576115c861395e565b5b6020026020010181905290506001855f0151607f8416815181106115f0576115ef61395e565b5b6020026020010190600181111561160a57611609613d80565b5b9081600181111561161e5761161d613d80565b5b81525050611631835f8360208751612a8c565b82518060208301525050505b505050565b61164a61300e565b5f8360f81c60ff16905060ff81036116655784915050611812565b5f60808216146117085760fe8103611692578280602001905181019061168b9190614233565b9450611703565b5f60208401519050602081146116dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d4906142ea565b60405180910390fd5b5f8660200151905060208551036020860152602085016020607f85160260208301015250505b6117c1565b602083511115611799575f602067ffffffffffffffff81111561172e5761172d613053565b5b6040519080825280601f01601f1916602001820160405280156117605781602001600182028036833780820191505090505b50905060208401516020820152808660200151607f8416815181106117885761178761395e565b5b6020026020010181905250506117c0565b828560200151607f8316815181106117b4576117b361395e565b5b60200260200101819052505b5b5f855f0151607f8316815181106117db576117da61395e565b5b602002602001019060018111156117f5576117f4613d80565b5b9081600181111561180957611808613d80565b5b81525050849150505b9392505050565b60605f600490505f602090505f805b60208110156119635760ff60f81b8782602081106118495761184861395e565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160315611963575f602088836020811061188b5761188a61395e565b5b1a60f81b60f81c60ff160290505f8860018401602081106118af576118ae61395e565b5b1a60f81b60f81c60ff16905060ff81036118d55785359350602086019550819450611956565b60fe81036118f25785359350600194506020860195505050611963565b60fd810361190557602086019550611955565b5f60808216146119225781860195506020607f8216029450611954565b5f8103611942575f82870190508035925082870196506020955050611953565b808202915081860195506020810294505b5b5b5b6002830192505050611828565b5060208214801561197357505f81145b156119b4575f8760200151607f8716815181106119935761199261395e565b5b60200260200101519050833560208201526020815280945050505050611acc565b5f81146119c6576020828202016119c8565b815b915060605f602090505f6080881614611a41576020840193508367ffffffffffffffff8111156119fb576119fa613053565b5b6040519080825280601f01601f191660200182016040528015611a2d5781602001600182028036833780820191505090505b509150602081830152602081019050611a91565b8367ffffffffffffffff811115611a5b57611a5a613053565b5b6040519080825280601f01601f191660200182016040528015611a8d5781602001600182028036833780820191505090505b5091505b5f8314611aa45782818301526020810190505b5b838111611ac357843581830152602081019050602085019450611aa5565b81955050505050505b9392505050565b60605f611ae4845f60e01b85610f97565b90505f600482510367ffffffffffffffff811115611b0557611b04613053565b5b6040519080825280601f01601f191660200182016040528015611b375781602001600182028036833780820191505090505b509050611b49826004835f8551612a8c565b809250505092915050565b607f820315611cc6575f611b718587612aa690919063ffffffff16565b90505f6080605886901b60f81c60ff161603611bfd575f611b9e846020896129b59092919063ffffffff16565b905060208152602082015160208201525f875f01518581518110611bc557611bc461395e565b5b60200260200101906001811115611bdf57611bde613d80565b5b90816001811115611bf357611bf2613d80565b5b8152505050611cc4565b5f6040831614611c56576001865f01518481518110611c1f57611c1e61395e565b5b60200260200101906001811115611c3957611c38613d80565b5b90816001811115611c4d57611c4c613d80565b5b81525050611ca0565b5f865f01518481518110611c6d57611c6c61395e565b5b60200260200101906001811115611c8757611c86613d80565b5b90816001811115611c9b57611c9a613d80565b5b815250505b8086602001518481518110611cb857611cb761395e565b5b60200260200101819052505b505b5050505050565b5f611cf785607f865f60208110611ce757611ce661395e565b5b1a60f81b60f81c60ff161661295f565b90505f611d2486607f87600160208110611d1457611d1361395e565b5b1a60f81b60f81c60ff161661295f565b90505f611d32848484612b27565b9050611d4985828961297d9092919063ffffffff16565b50505050505050565b5f60606001611d89607f855f60208110611d6f57611d6e61395e565b5b1a60f81b60f81c60ff16168661295f90919063ffffffff16565b03611da857600160405180602001604052805f81525091509150611e66565b5f60ff60f81b84600160208110611dc257611dc161395e565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611e28576040518060400160405280601081526020017f417373657274696f6e206661696c656400000000000000000000000000000000815250611e5c565b611e5b607f85600160208110611e4157611e4061395e565b5b1a60f81b60f81c60ff161686612d0290919063ffffffff16565b5b90505f8192509250505b9250929050565b5f611e9d835f60208110611e8457611e8361395e565b5b1a60f81b60f81c60ff1685612a5b90919063ffffffff16565b90505f805f600190505b6020811015611f385760ff868260208110611ec557611ec461395e565b5b1a60f81b60f81c60ff160315611f3857600183611ee29190613e15565b92505f84600183611ef3919061415f565b60208110611f0457611f0361395e565b5b1a60f81b60f81c90505f6008821660ff1614611f2a57600183611f279190613e15565b92505b508080600101915050611ea7565b505f8267ffffffffffffffff811115611f5457611f53613053565b5b604051908082528060200260200182016040528015611f825781602001602082028036833780820191505090505b5090505f8267ffffffffffffffff811115611fa057611f9f613053565b5b604051908082528060200260200182016040528015611fd357816020015b6060815260200190600190039081611fbe5790505b5090505f92505f5b602081101561214c575f868260208110611ff857611ff761395e565b5b1a60f81b60f81c90505f896001846120109190613e15565b602081106120215761202061395e565b5b1a60f81b60f81c905060ff8260ff16148061203f575060ff8160ff16145b1561204b57505061214c565b5f8260ff16036120965761206e607f8260ff16168c61295f90919063ffffffff16565b5f1b8584815181106120835761208261395e565b5b602002602001018181525050505061213f565b5f6008831660ff16036120cf578060ff165f1b8584815181106120bc576120bb61395e565b5b602002602001018181525050505061213f565b855f1b8584815181106120e5576120e461395e565b5b6020026020010181815250505f61210b607f8360ff16168d612d0290919063ffffffff16565b9050808588815181106121215761212061395e565b5b60200260200101819052506001876121399190613e15565b96505050505b8080600101915050611fdb565b5063ffffffff86167f2d55a493edb2b612d60bd0b2564ad76fc84b787faef25e1e426091777a99db5c8383604051602001612188929190614442565b6040516020818303038152906040526040516121a49190614477565b60405180910390a25050505050505050565b5f6121e9607f855f602081106121cf576121ce61395e565b5b1a60f81b60f81c60ff16168661295f90919063ffffffff16565b90505f6121f68383612d2b565b905061220d84828861297d9092919063ffffffff16565b505050505050565b5f810361223f575f6122308385611ad390919063ffffffff16565b9050805160208201a05061256a565b600181036122a9575f612277835f6020811061225e5761225d61395e565b5b1a60f81b60f81c60ff1685612a5b90919063ffffffff16565b90505f61229860ff6008865f1c901b175f1b86611ad390919063ffffffff16565b905081815160208301a15050612569565b60028103612349575f6122e1835f602081106122c8576122c761395e565b5b1a60f81b60f81c60ff1685612a5b90919063ffffffff16565b90505f612314846001602081106122fb576122fa61395e565b5b1a60f81b60f81c60ff1686612a5b90919063ffffffff16565b90505f61233661ffff6010875f1c901b175f1b87611ad390919063ffffffff16565b90508183825160208401a2505050612568565b6003810361241f575f612381835f602081106123685761236761395e565b5b1a60f81b60f81c60ff1685612a5b90919063ffffffff16565b90505f6123b48460016020811061239b5761239a61395e565b5b1a60f81b60f81c60ff1686612a5b90919063ffffffff16565b90505f6123e7856002602081106123ce576123cd61395e565b5b1a60f81b60f81c60ff1687612a5b90919063ffffffff16565b90505f61240a62ffffff6018885f1c901b175f1b88611ad390919063ffffffff16565b9050818385835160208501a350505050612567565b6004810361252b575f612457835f6020811061243e5761243d61395e565b5b1a60f81b60f81c60ff1685612a5b90919063ffffffff16565b90505f61248a846001602081106124715761247061395e565b5b1a60f81b60f81c60ff1686612a5b90919063ffffffff16565b90505f6124bd856002602081106124a4576124a361395e565b5b1a60f81b60f81c60ff1687612a5b90919063ffffffff16565b90505f6124f0866003602081106124d7576124d661395e565b5b1a60f81b60f81c60ff1688612a5b90919063ffffffff16565b90505f61251463ffffffff6020895f1c901b175f1b89611ad390919063ffffffff16565b905081838587845160208601a45050505050612566565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161255d906144e1565b60405180910390fd5b5b5b5b5b505050565b5f6125a2607f835f602081106125885761258761395e565b5b1a60f81b60f81c60ff161684612d0290919063ffffffff16565b9050600180846040015116036125ed577f80ae80e2be1b30839508ea0fa59b88194af0e9957c7b9862b55f48d0e716b6db6001826040516125e4929190613d2b565b60405180910390a15b805160208201f35b61262e5f612629846002602081106126105761260f61395e565b5b1a60f81b60f81c60ff168661295f90919063ffffffff16565b612d6a565b61266860016126638460036020811061264a5761264961395e565b5b1a60f81b60f81c60ff168661295f90919063ffffffff16565b612d6a565b5f8360200151607f845f602081106126835761268261395e565b5b1a60f81b60f81c60ff16168151811061269f5761269e61395e565b5b6020026020010151905060606020820190505f855f015184815181106126c8576126c761395e565b5b602002602001019060018111156126e2576126e1613d80565b5b908160018111156126f6576126f5613d80565b5b815250505f60ff8660400151166008808860400151901c60016127199190613e15565b901b1790505f808284895f01518a6020015160405160200161273f9594939291906145b9565b6040516020818303038152906040529050602081510360208201526020606082015103606082015260206080820151036080820152602060a08201510360a082015280876020015186815181106127995761279861395e565b5b602002602001018190525050505050505050565b6060607f82036127cd5760405180602001604052805f8152509050612958565b5f612800607f855f602081106127e6576127e561395e565b5b1a60f81b60f81c60ff161686612a5b90919063ffffffff16565b90505f612836607f8660016020811061281c5761281b61395e565b5b1a60f81b60f81c60ff161687612d0290919063ffffffff16565b90505f61286c607f876002602081106128525761285161395e565b5b1a60f81b60f81c60ff161688612a5b90919063ffffffff16565b90505f6128798385612d71565b50509050602084601f602081106128935761289261395e565b5b1a60f81b60f81c0260ff1681019050818184015282886020015187815181106128bf576128be61395e565b5b6020026020010181905250875f0151607f886001602081106128e4576128e361395e565b5b1a60f81b60f81c60ff161681518110612900576128ff61395e565b5b6020026020010151885f0151878151811061291e5761291d61395e565b5b6020026020010190600181111561293857612937613d80565b5b9081600181111561294c5761294b613d80565b5b81525050829450505050505b9392505050565b5f6129738284612a5b90919063ffffffff16565b5f1c905092915050565b607f8203156129b0575f8360200151838151811061299e5761299d61395e565b5b60200260200101519050816020820152505b505050565b6060836020015183815181106129ce576129cd61395e565b5b602002602001015190508181511015612a54578167ffffffffffffffff8111156129fb576129fa613053565b5b6040519080825280601f01601f191660200182016040528015612a2d5781602001600182028036833780820191505090505b5090508084602001518481518110612a4857612a4761395e565b5b60200260200101819052505b9392505050565b5f8083602001518381518110612a7457612a7361395e565b5b60200260200101519050602081015191505092915050565b808260208501018286602089010160045afa505050505050565b60605f612adb607f845f60208110612ac157612ac061395e565b5b1a60f81b60f81c60ff161685612a5b90919063ffffffff16565b90505f612b11607f85600160208110612af757612af661395e565b5b1a60f81b60f81c60ff161686612d0290919063ffffffff16565b9050612b1d8183612ec7565b9250505092915050565b5f60ff84165f8114612bf75760018114612c015760028114612c0b5760038114612c155760048114612c1f5760058114612c295760068114612c335760078114612c3d5760088114612c475760098114612c5257600a8114612c5d57600b8114612c6857600c8114612c7257600d8114612c7c57600e8114612c8657600f8114612c905760108114612c9a5760118114612ca45760128114612cb25760238114612cc05760268114612cca5760278114612cd45760288114612cde5760298114612ce957602b8114612cf4575f80fd5b8284019150612cfa565b8284039150612cfa565b8284029150612cfa565b8284049150612cfa565b82840a9150612cfa565b8284149150612cfa565b8284109150612cfa565b8284119150612cfa565b828411159150612cfa565b828410159150612cfa565b828414159150612cfa565b8284069150612cfa565b8284169150612cfa565b8284179150612cfa565b8284189150612cfa565b83831b9150612cfa565b83831c9150612cfa565b821515841515169150612cfa565b821515841515179150612cfa565b8284059150612cfa565b8284139150612cfa565b8284139150612cfa565b828413159150612cfa565b828412159150612cfa565b82840791505b509392505050565b606082602001518281518110612d1b57612d1a61395e565b5b6020026020010151905092915050565b5f60ff83165f8114612d4b5760018114612d555760028114612d5e575f80fd5b825f039150612d63565b82199150612d63565b821591505b5092915050565b80825d5050565b5f805f60209250602091505f90505f5b6020811015612ebf5760ff60f81b858260208110612da257612da161395e565b5b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160315612ebf575f6020868360208110612de457612de361395e565b5b1a60f81b60f81c60ff160290505f866001840160208110612e0857612e0761395e565b5b1a60f81b60f81c60ff16905060ff8103612e2d57858801519350602086019550612eb2565b60fe8103612e4c57858801519350602086019550600194505050612ebf565b60fd8103612e5f57602086019550612eb1565b5f6080821614612e7c5781860195506020607f8216029450612eb0565b5f8103612e9e575f828701905080890151925082870196506020955050612eaf565b808202915081860195506020810294505b5b5b5b6002830192505050612d81565b509250925092565b60605f805f612ed68686612d71565b925092509250602082148015612eeb57505f81145b15612f25578286015192505f83604051602001612f08919061461f565b604051602081830303815290604052905080945050505050612fed565b5f808214612f4a578282612f399190614638565b6020612f459190613e15565b612f58565b602083612f579190613e15565b5b67ffffffffffffffff811115612f7157612f70613053565b5b6040519080825280601f01601f191660200182016040528015612fa35781602001600182028036833780820191505090505b5090505f879050602085612fb7919061415f565b94505f831115612fd157602085612fce919061415f565b94505b8488019050612fe4815f845f8651612a8c565b81955050505050505b92915050565b60405180604001604052805f15158152602001606081525090565b604051806060016040528060608152602001606081526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61308982613043565b810181811067ffffffffffffffff821117156130a8576130a7613053565b5b80604052505050565b5f6130ba61302e565b90506130c68282613080565b919050565b5f67ffffffffffffffff8211156130e5576130e4613053565b5b602082029050602081019050919050565b5f80fd5b5f819050919050565b61310c816130fa565b8114613116575f80fd5b50565b5f8135905061312781613103565b92915050565b5f61313f61313a846130cb565b6130b1565b90508083825260208201905060208402830185811115613162576131616130f6565b5b835b8181101561318b57806131778882613119565b845260208401935050602081019050613164565b5050509392505050565b5f82601f8301126131a9576131a861303f565b5b81356131b984826020860161312d565b91505092915050565b5f67ffffffffffffffff8211156131dc576131db613053565b5b602082029050602081019050919050565b5f80fd5b5f67ffffffffffffffff82111561320b5761320a613053565b5b61321482613043565b9050602081019050919050565b828183375f83830152505050565b5f61324161323c846131f1565b6130b1565b90508281526020810184848401111561325d5761325c6131ed565b5b613268848285613221565b509392505050565b5f82601f8301126132845761328361303f565b5b813561329484826020860161322f565b91505092915050565b5f6132af6132aa846131c2565b6130b1565b905080838252602082019050602084028301858111156132d2576132d16130f6565b5b835b8181101561331957803567ffffffffffffffff8111156132f7576132f661303f565b5b8086016133048982613270565b855260208501945050506020810190506132d4565b5050509392505050565b5f82601f8301126133375761333661303f565b5b813561334784826020860161329d565b91505092915050565b5f819050919050565b61336281613350565b811461336c575f80fd5b50565b5f8135905061337d81613359565b92915050565b5f805f6060848603121561339a57613399613037565b5b5f84013567ffffffffffffffff8111156133b7576133b661303b565b5b6133c386828701613195565b935050602084013567ffffffffffffffff8111156133e4576133e361303b565b5b6133f086828701613323565b92505060406134018682870161336f565b9150509250925092565b5f8115159050919050565b61341f8161340b565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f61345782613425565b613461818561342f565b935061347181856020860161343f565b61347a81613043565b840191505092915050565b5f604083015f83015161349a5f860182613416565b50602083015184820360208601526134b2828261344d565b9150508091505092915050565b5f6020820190508181035f8301526134d78184613485565b905092915050565b5f82825260208201905092915050565b7f496e76616c69642063616c6c6261636b000000000000000000000000000000005f82015250565b5f6135236010836134df565b915061352e826134ef565b602082019050919050565b5f6020820190508181035f83015261355081613517565b9050919050565b5f8151905061356581613359565b92915050565b5f8151905061357981613103565b92915050565b5f61359161358c846130cb565b6130b1565b905080838252602082019050602084028301858111156135b4576135b36130f6565b5b835b818110156135dd57806135c9888261356b565b8452602084019350506020810190506135b6565b5050509392505050565b5f82601f8301126135fb576135fa61303f565b5b815161360b84826020860161357f565b91505092915050565b5f67ffffffffffffffff82111561362e5761362d613053565b5b602082029050602081019050919050565b6002811061364b575f80fd5b50565b5f8151905061365c8161363f565b92915050565b5f61367461366f84613614565b6130b1565b90508083825260208201905060208402830185811115613697576136966130f6565b5b835b818110156136c057806136ac888261364e565b845260208401935050602081019050613699565b5050509392505050565b5f82601f8301126136de576136dd61303f565b5b81516136ee848260208601613662565b91505092915050565b5f613709613704846131f1565b6130b1565b905082815260208101848484011115613725576137246131ed565b5b61373084828561343f565b509392505050565b5f82601f83011261374c5761374b61303f565b5b815161375c8482602086016136f7565b91505092915050565b5f613777613772846131c2565b6130b1565b9050808382526020820190506020840283018581111561379a576137996130f6565b5b835b818110156137e157805167ffffffffffffffff8111156137bf576137be61303f565b5b8086016137cc8982613738565b8552602085019450505060208101905061379c565b5050509392505050565b5f82601f8301126137ff576137fe61303f565b5b815161380f848260208601613765565b91505092915050565b5f805f80608085870312156138305761382f613037565b5b5f61383d87828801613557565b945050602085015167ffffffffffffffff81111561385e5761385d61303b565b5b61386a878288016135e7565b935050604085015167ffffffffffffffff81111561388b5761388a61303b565b5b613897878288016136ca565b925050606085015167ffffffffffffffff8111156138b8576138b761303b565b5b6138c4878288016137eb565b91505092959194509250565b7f50726576656e7454616d706572696e673a20436f646520686173206368616e675f8201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b5f61392a6022836134df565b9150613935826138d0565b604082019050919050565b5f6020820190508181035f8301526139578161391e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6139c282613350565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036139f4576139f361398b565b5b600182019050919050565b613a0881613350565b82525050565b613a17816130fa565b82525050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613a4682613a1d565b9050919050565b613a5681613a3c565b82525050565b5f82825260208201905092915050565b5f613a7682613425565b613a808185613a5c565b9350613a9081856020860161343f565b613a9981613043565b840191505092915050565b5f60a082019050613ab75f8301886139ff565b613ac46020830187613a0e565b613ad16040830186613a4d565b8181036060830152613ae38185613a6c565b9050613af260808301846139ff565b9695505050505050565b5f81905092915050565b5f613b1082613425565b613b1a8185613afc565b9350613b2a81856020860161343f565b80840191505092915050565b5f613b418284613b06565b915081905092915050565b7f5f657865637574653a2076616c75652063616c6c20686173206e6f2076616c755f8201527f6520696e646963617465642e0000000000000000000000000000000000000000602082015250565b5f613ba6602c836134df565b9150613bb182613b4c565b604082019050919050565b5f6020820190508181035f830152613bd381613b9a565b9050919050565b7f496e76616c69642063616c6c74797065000000000000000000000000000000005f82015250565b5f613c0e6010836134df565b9150613c1982613bda565b602082019050919050565b5f6020820190508181035f830152613c3b81613c02565b9050919050565b613c4b8161340b565b82525050565b5f608082019050613c645f8301876139ff565b613c716020830186613a0e565b613c7e6040830185613c42565b8181036060830152613c908184613a6c565b905095945050505050565b5f604082019050613cae5f8301856139ff565b8181036020830152613cc08184613a6c565b90509392505050565b5f81519050919050565b5f613cdd82613cc9565b613ce781856134df565b9350613cf781856020860161343f565b613d0081613043565b840191505092915050565b5f6020820190508181035f830152613d238184613cd3565b905092915050565b5f604082019050613d3e5f830185613c42565b8181036020830152613d508184613a6c565b90509392505050565b5f604082019050613d6c5f8301856139ff565b613d796020830184613a0e565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f81905092915050565b7f496e76616c696420696e7465726e616c20636f6d6d616e6400000000000000005f82015250565b5f613deb601883613dad565b9150613df682613db7565b601882019050919050565b5f613e0b82613ddf565b9150819050919050565b5f613e1f82613350565b9150613e2a83613350565b9250828201905080821115613e4257613e4161398b565b5b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b60028110613e8257613e81613d80565b5b50565b5f819050613e9282613e71565b919050565b5f613ea182613e85565b9050919050565b613eb181613e97565b82525050565b5f613ec28383613ea8565b60208301905092915050565b5f602082019050919050565b5f613ee482613e48565b613eee8185613e52565b9350613ef983613e62565b805f5b83811015613f29578151613f108882613eb7565b9750613f1b83613ece565b925050600181019050613efc565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f613f6a838361344d565b905092915050565b5f602082019050919050565b5f613f8882613f36565b613f928185613f40565b935083602082028501613fa485613f50565b805f5b85811015613fdf5784840389528151613fc08582613f5f565b9450613fcb83613f72565b925060208a01995050600181019050613fa7565b50829750879550505050505092915050565b613ffa81613350565b82525050565b5f606083015f8301518482035f86015261401a8282613eda565b915050602083015184820360208601526140348282613f7e565b91505060408301516140496040860182613ff1565b508091505092915050565b5f6020820190508181035f83015261406c8184614000565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6140ab82613350565b91506140b683613350565b9250826140c6576140c5614074565b5b828206905092915050565b7f44796e616d6963207374617465207661726961626c6573206d757374206265205f8201527f61206d756c7469706c65206f6620333220627974657300000000000000000000602082015250565b5f61412b6036836134df565b9150614136826140d1565b604082019050919050565b5f6020820190508181035f8301526141588161411f565b9050919050565b5f61416982613350565b915061417483613350565b925082820390508181111561418c5761418b61398b565b5b92915050565b5f80fd5b5f80fd5b5f606082840312156141af576141ae614192565b5b6141b960606130b1565b90505f82015167ffffffffffffffff8111156141d8576141d7614196565b5b6141e4848285016136ca565b5f83015250602082015167ffffffffffffffff81111561420757614206614196565b5b614213848285016137eb565b602083015250604061422784828501613557565b60408301525092915050565b5f6020828403121561424857614247613037565b5b5f82015167ffffffffffffffff8111156142655761426461303b565b5b6142718482850161419a565b91505092915050565b7f4f6e6c79206f6e652072657475726e2076616c7565207065726d6974746564205f8201527f287661726961626c652900000000000000000000000000000000000000000000602082015250565b5f6142d4602a836134df565b91506142df8261427a565b604082019050919050565b5f6020820190508181035f830152614301816142c8565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61433a816130fa565b82525050565b5f61434b8383614331565b60208301905092915050565b5f602082019050919050565b5f61436d82614308565b6143778185614312565b935061438283614322565b805f5b838110156143b25781516143998882614340565b97506143a483614357565b925050600181019050614385565b5085935050505092915050565b5f82825260208201905092915050565b5f6143d982613f36565b6143e381856143bf565b9350836020820285016143f585613f50565b805f5b8581101561443057848403895281516144118582613f5f565b945061441c83613f72565b925060208a019950506001810190506143f8565b50829750879550505050505092915050565b5f6040820190508181035f83015261445a8185614363565b9050818103602083015261446e81846143cf565b90509392505050565b5f6020820190508181035f83015261448f8184613a6c565b905092915050565b7f496e76616c6964206e756d626572206f6620746f7069637300000000000000005f82015250565b5f6144cb6018836134df565b91506144d682614497565b602082019050919050565b5f6020820190508181035f8301526144f8816144bf565b9050919050565b5f819050919050565b5f60ff82169050919050565b5f819050919050565b5f61453761453261452d846144ff565b614514565b614508565b9050919050565b6145478161451d565b82525050565b5f82825260208201905092915050565b5f61456782613e48565b614571818561454d565b935061457c83613e62565b805f5b838110156145ac5781516145938882613eb7565b975061459e83613ece565b92505060018101905061457f565b5085935050505092915050565b5f60a0820190506145cc5f83018861453e565b6145d960208301876139ff565b81810360408301526145eb8186614363565b905081810360608301526145ff818561455d565b9050818103608083015261461381846143cf565b90509695505050505050565b5f6020820190506146325f8301846139ff565b92915050565b5f61464282613350565b915061464d83613350565b925082820261465b81613350565b915082820484148315176146725761467161398b565b5b509291505056fea26469706673582212207ce861eae468bd6b57b718bc270a7b53d782596b6e5e4341c1d1d35d9b253cb464736f6c634300081a0033
Verified Source Code Full Match
Compiler: v0.8.26+commit.8a97fa7a
EVM: cancun
Optimization: No
PreventTampering.sol 17 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
abstract contract PreventTampering {
modifier revertOnCodeHashChange() {
bytes32 hashBefore;
assembly {
hashBefore := extcodehash(address())
}
_;
bytes32 hashPostExecution;
assembly {
hashPostExecution := extcodehash(address())
}
require(hashPostExecution == hashBefore, "PreventTampering: Code has changed");
}
}
Runtime.sol 39 lines
// SPDX-License-Identifier: BlueOak-1.0.0
pragma solidity 0.8.26;
import { DataTag } from "./weiroll/CommandBuilder.sol";
import { PreventTampering } from "./PreventTampering.sol";
import { VM, VMOutput, VMState } from "./weiroll/VM.sol";
/** Unpermissioned VM implementation:
* Do not leave funds here as anyone can grab them.
*/
contract Runtime is VM, PreventTampering {
fallback() external payable {
fallbackHook();
}
function execute(
bytes32[] memory commands,
bytes[] memory state,
uint256 flags
) revertOnCodeHashChange()
public
payable
returns (VMOutput memory out)
{
VMState memory vmstate = VMState(
new DataTag[](state.length),
state,
flags
);
out = _execute(
vmstate,
commands
);
}
receive() external payable {}
}
CommandBuilder.sol 241 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import { VMState, DataTag } from "./VMState.sol";
library CommandBuilder {
uint256 constant IDX_VARIABLE_LENGTH = 0x80;
uint256 constant IDX_VALUE_MASK = 0x7f;
uint256 constant IDX_END_OF_ARGS = 0xff;
uint256 constant IDX_USE_STATE = 0xfe;
function buildInputs(
VMState memory state,
bytes4 selector,
bytes32 indices
) internal view returns (bytes memory ret) {
uint256 count; // Number of bytes in whole ABI encoded message
uint256 free; // Pointer to first free byte in tail part of message
bytes memory stateData; // Optionally encode the current state if the call requires it
uint256 idx;
// Determine the length of the encoded data
for (uint256 i; i < 32;) {
idx = uint8(indices[i]);
if (idx == IDX_END_OF_ARGS) break;
if (state.meta[idx & IDX_VALUE_MASK] == DataTag.TUPLE) {
uint256 len = state.data[idx & IDX_VALUE_MASK].length;
if (idx & IDX_VARIABLE_LENGTH != 0) {
count += len + 32;
free += 32;
i++;
} else {
count += len;
free += len;
i++;
}
continue;
}
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_USE_STATE) {
if (stateData.length == 0) {
stateData = abi.encode(state);
}
count += stateData.length;
} else {
// Add the size of the value, rounded up to the next word boundary, plus space for pointer and length
uint256 arglen = state.data[idx & IDX_VALUE_MASK].length;
require(
arglen % 32 == 0,
"Dynamic state variables must be a multiple of 32 bytes"
);
count += arglen + 32;
}
} else {
count += state.data[idx & IDX_VALUE_MASK].length;
}
free += 32;
i++;
}
// Encode it
ret = new bytes(count + 4);
assembly {
mstore(add(ret, 32), selector)
}
count = 0;
for (uint256 i; i < 32;) {
idx = uint8(indices[i]);
if (idx == IDX_END_OF_ARGS) break;
if (state.meta[idx & IDX_VALUE_MASK] == DataTag.TUPLE) {
if (idx & IDX_VARIABLE_LENGTH != 0) {
uint256 len = state.data[idx & IDX_VALUE_MASK].length;
// Write the pointer to the data
assembly {
mstore(add(add(ret, 36), count), free)
}
memcpy(
state.data[idx & IDX_VALUE_MASK],
0,
ret,
free + 4,
len
);
free += len;
count += 32;
i++;
} else {
uint256 len = state.data[idx & IDX_VALUE_MASK].length;
memcpy(
state.data[idx & IDX_VALUE_MASK],
0,
ret,
count + 4,
len
);
i++;
count += len;
}
continue;
}
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_USE_STATE) {
assembly {
mstore(add(add(ret, 36), count), free)
}
memcpy(stateData, 32, ret, free + 4, stateData.length - 32);
free += stateData.length - 32;
} else {
uint256 arglen = state.data[idx & IDX_VALUE_MASK].length;
// Variable length data; put a pointer in the slot and write the data at the end
assembly {
mstore(add(add(ret, 36), count), free)
}
memcpy(
state.data[idx & IDX_VALUE_MASK],
0,
ret,
free + 4,
arglen
);
free += arglen;
}
} else {
// Fixed length data; write it directly
bytes memory buff = state.data[idx & IDX_VALUE_MASK];
assembly {
mstore(add(add(ret, 36), count), mload(add(buff, 32)))
}
}
count += 32;
i++;
}
}
function writeOutputs(
VMState memory state,
bytes1 index,
bytes memory output
) internal pure returns (VMState memory) {
uint256 idx = uint8(index);
if (idx == IDX_END_OF_ARGS) return state;
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_USE_STATE) {
state = abi.decode(output, (VMState));
} else {
// Check the first field is 0x20 (because we have only a single return value)
uint256 argptr;
assembly {
argptr := mload(add(output, 32))
}
require(
argptr == 32,
"Only one return value permitted (variable)"
);
bytes[] memory data = state.data;
assembly {
// Overwrite the first word of the return data with the length - 32
mstore(add(output, 32), sub(mload(output), 32))
// Insert a pointer to the return data, starting at the second word, into state
mstore(
add(add(data, 32), mul(and(idx, IDX_VALUE_MASK), 32)),
add(output, 32)
)
}
}
} else {
// Single word
if (output.length > 32) {
bytes memory newOut = new bytes(32);
assembly {
mstore(add(newOut, 32), mload(add(output, 32)))
}
state.data[idx & IDX_VALUE_MASK] = newOut;
} else {
state.data[idx & IDX_VALUE_MASK] = output;
}
}
state.meta[idx & IDX_VALUE_MASK] = DataTag.DEFAULT;
return state;
}
function writeTuple(
VMState memory state,
bytes1 index,
bytes memory output
) internal view {
uint256 idx = uint256(uint8(index));
if (idx == IDX_END_OF_ARGS) return;
bytes memory entry = state.data[idx & IDX_VALUE_MASK] = new bytes(output.length + 32);
state.meta[idx & IDX_VALUE_MASK] = DataTag.TUPLE;
memcpy(output, 0, entry, 32, output.length);
assembly {
let l := mload(output)
mstore(add(entry, 32), l)
}
}
function memcpy(
bytes memory src,
uint256 srcidx,
bytes memory dest,
uint256 destidx,
uint256 len
) internal view {
assembly {
pop(
staticcall(
gas(),
4,
add(add(src, 32), srcidx),
len,
add(add(dest, 32), destidx),
len
)
)
}
}
}
MathOpCodes.sol 122 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
library MathOpCodes {
function binaryOp(
uint256 op,
uint256 a,
uint256 b
) internal pure returns (uint256 c) {
assembly {
switch and(op, 0xff)
case 0 { // c = a + b
c := add(a, b)
}
case 1 { // c = a - b
c := sub(a, b)
}
case 2 { // c = a * b
c := mul(a, b)
}
case 3 { // c = a / b
c := div(a, b)
}
case 4 { // c = a ** b
c := exp(a, b)
}
case 5 { // c = a == b
c := eq(a, b)
}
case 6 { // c = a < b
c := lt(a, b)
}
case 7 { // c = a > b
c := gt(a, b)
}
case 8 { // c = a <= b
c := iszero(gt(a, b))
}
case 9 { // c = a >= b
c := iszero(lt(a, b))
}
case 10 { // c = a != b
c := iszero(eq(a, b))
}
case 11 { // c = a % b
c := mod(a, b)
}
case 12 { // c = a & b
c := and(a, b)
}
case 13 { // c = a | b
c := or(a, b)
}
case 14 { // c = a ^ b
c := xor(a, b)
}
case 15 { // c = a << b
c := shl(b, a)
}
case 16 { // c = a >> b
c := shr(b, a)
}
case 17 { // c = a && b
c := and(iszero(iszero(a)), iszero(iszero(b)))
}
case 18 { // c = a || b
c := or(iszero(iszero(a)), iszero(iszero(b)))
}
// case 17 { // (x + y) % m
// c := addmod(a, b, mload(add(din, 32)))
// }
// case 18 { // c = x * y) % m
// c := mulmod(a, b, mload(add(din, 32)))
// }
// op | 32 for signed sdiv, smod, slt, sgt, sar
// signed ops
case 35 {
c := sdiv(a, b)
}
case 38 {
c := sgt(a, b)
}
case 39 {
c := sgt(a, b)
}
case 40 { // c = a <= b
c := iszero(sgt(a, b))
}
case 41 { // c = a >= b
c := iszero(slt(a, b))
}
case 43 {
c := smod(a, b)
}
default {
revert(0, 0)
}
}
}
function unaryOp(
uint256 op,
uint256 a
) internal pure returns (uint256 b) {
assembly {
switch and(op, 0xff)
case 0 { // -a
b := sub(0, a)
}
case 1 { // ~a
b := not(a)
}
case 2 { // !a
b := iszero(a)
}
default {
revert(0, 0)
}
}
}
}
Memory.sol 294 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import { VMState } from "./VMState.sol";
import { CommandBuilder } from "./CommandBuilder.sol";
library Memory {
using Memory for VMState;
using CommandBuilder for VMState;
function readBuffer(
VMState memory state,
uint256 idx
) internal pure returns (bytes memory out) {
out = state.data[idx];
}
function readValue(
VMState memory state, uint256 idx
) internal pure returns (bytes32 out) {
bytes memory data = state.data[idx];
assembly {
out := mload(add(data, 32))
}
}
function getBufferForSlot(VMState memory state, uint256 idx, uint256 minLength) internal pure returns (bytes memory out) {
out = state.data[idx];
if (out.length < minLength) {
out = new bytes(minLength);
state.data[idx] = out;
}
}
function readUint256(
VMState memory state, uint256 idx
) internal pure returns (uint256 out) {
out = uint256(state.readValue(idx));
}
function followPath(bytes memory root, bytes32 path) internal pure returns (
uint256 rootOffset,
uint256 size,
uint256 entries
) {
unchecked{
rootOffset = 32;
size = 32;
entries = 0;
for(uint256 i; i < 32;) {
if (path[i] == 0xff) break;
uint256 elementOffset = uint256(uint8(path[i])) * 32;
uint256 s = uint256(uint8(path[i + 1]));
if (s == 0xff) { // Read size of array
assembly {
entries := mload(add(root, rootOffset))
}
rootOffset += 32;
} else if (s == 0xfe) { // Read length of array and set size to 1
assembly {
entries := mload(add(root, rootOffset))
}
rootOffset += 32;
size = 1;
break;
} else if (s == 0xfd) { // Discard length of array
rootOffset += 32;
} else if ((s & 128) != 0) {
rootOffset = rootOffset + elementOffset;
size = (s & 127) * 32;
} else if (s == 0) {
uint256 elementIndex = rootOffset + elementOffset;
assembly {
elementOffset := mload(add(root, elementIndex))
}
rootOffset += elementOffset;
size = 32;
} else {
elementOffset *= s;
rootOffset = rootOffset + elementOffset;
size = s * 32;
}
i += 2;
}
return ( rootOffset, size, entries );
}
}
function opCalldataRead(
VMState memory state,
bytes32 path,
uint256 outf
) internal pure returns (bytes memory) {
unchecked{
uint256 rootOffset = 4;
uint256 size = 32;
uint256 entries = 0;
for(uint256 i; i < 32;) {
if (path[i] == 0xff) break;
uint256 elementOffset = uint256(uint8(path[i])) * 32;
uint256 s = uint256(uint8(path[i + 1]));
// console.log("root == %s ; element = %s ; s = %s", rootOffset, elementOffset, s);
// Load array size if 0xff
if (s == 0xff) { // Read size of array
assembly {
entries := calldataload(rootOffset)
}
rootOffset += 32;
size = elementOffset;
} else if (s == 0xfe) { // Read length of array and set size to 1
assembly {
entries := calldataload(rootOffset)
}
size = 1;
rootOffset += 32;
break;
} else if (s == 0xfd) { // Discard length of array
rootOffset += 32;
} else if ((s & 128) != 0) {
rootOffset = rootOffset + elementOffset;
size = (s & 127) * 32;
} else if (s == 0) {
uint256 elementIndex = rootOffset + elementOffset;
// console.log("Reading from %s", elementIndex);
assembly {
elementOffset := calldataload(elementIndex)
}
// console.log("read offset %s", elementOffset);
rootOffset += elementOffset;
// console.log("new root %s", rootOffset);
size = 32;
} else {
elementOffset *= s;
rootOffset = rootOffset + elementOffset;
size = s * 32;
}
i += 2;
}
if (size == 32 && entries == 0) {
bytes memory out = state.data[outf & CommandBuilder.IDX_VALUE_MASK];
assembly {
mstore(add(out,32), calldataload(rootOffset))
mstore(out, 32)
}
return out;
} else {
size = entries == 0 ? size : entries * size + 32;
bytes memory out;
uint256 j = 32;
if (outf & CommandBuilder.IDX_VARIABLE_LENGTH != 0) {
size += 32;
out = new bytes(size);
assembly {
mstore(add(out, j), 32)
}
j += 32;
} else {
out = new bytes(size);
}
if (entries != 0) {
assembly {
mstore(add(out, j), entries)
}
j += 32;
}
for (; j <= size;) {
assembly {
mstore(add(out, j), calldataload(rootOffset))
j := add(j, 32)
rootOffset := add(rootOffset, 32)
}
}
return out;
}
}
}
function makeTuple(
VMState memory state,
bytes32 indices
) internal view returns (bytes memory) {
unchecked{
bytes memory o = CommandBuilder.buildInputs(
state,
bytes4(0),
indices
);
bytes memory out = new bytes(o.length - 4);
CommandBuilder.memcpy(
o,
4,
out,
0,
out.length
);
return out;
}
}
function writeWord(VMState memory state, uint256 slot, uint256 value) internal pure {
if (slot == 127) {
return;
}
bytes memory buff = state.data[slot];
assembly {
mstore(add(buff, 32), value)
}
}
function opMStore(
VMState memory state,
bytes32 indices,
uint256 outf
) internal pure returns (bytes memory) {
if (outf == 127) {
return bytes("");
}
unchecked {
bytes32 path = state.readValue(
uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK
);
bytes memory root = state.readBuffer(
uint8(indices[1]) & CommandBuilder.IDX_VALUE_MASK
);
bytes32 value = state.readValue(
uint8(indices[2]) & CommandBuilder.IDX_VALUE_MASK
);
(uint256 rootOffset,,) = followPath(root, path);
rootOffset += uint8(path[31]) * 32;
assembly {
mstore(add(root, rootOffset), value)
}
state.data[outf] = root;
state.meta[outf] = state.meta[uint8(indices[1]) & CommandBuilder.IDX_VALUE_MASK];
// console.logBytes(root);
return root;
}
}
function followPathRead(
bytes memory root,
bytes32 path
) internal view returns (bytes memory out) {
(uint256 rootOffset, uint256 size, uint256 entries) = followPath(root, path);
if (size == 32 && entries == 0) {
assembly {
rootOffset := mload(add(root, rootOffset))
}
bytes memory output = abi.encode(rootOffset);
return output;
} else {
bytes memory output = new bytes(entries == 0 ? size + 32 : 32 + entries * size);
bytes memory source = root;
rootOffset -= 32;
if (entries > 0) {
rootOffset -= 32;
}
assembly {
source := add(root, rootOffset)
}
CommandBuilder.memcpy(source, 0, output, 0, output.length);
return output;
}
}
function readMemory(
VMState memory state,
bytes32 indices
) internal view returns (bytes memory) {
unchecked{
bytes32 path = state.readValue(
uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK
);
bytes memory root = state.readBuffer(
uint8(indices[1]) & CommandBuilder.IDX_VALUE_MASK
);
return followPathRead(root, path);
}
}
}
TransientStorage.sol 15 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
library TransientStorage {
function tread(uint256 key) internal view returns (uint256 value) {
assembly {
value := tload(key)
}
}
function twrite(uint256 key, uint256 value) internal {
assembly {
tstore(key, value)
}
}
}
VM.sol 570 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import { VMState, VMOutput, DataTag } from "./VMState.sol";
import { CommandBuilder } from "./CommandBuilder.sol";
import { Memory } from "./Memory.sol";
import { MathOpCodes } from "./MathOpCodes.sol";
import { TransientStorage } from "./TransientStorage.sol";
event VMException(uint256 cmdIndex, bytes msg);
event VMCall(uint256 cmdIndex, bytes32 cmd, address to, bytes data, uint256 callType);
event VMCallReturn(uint256 cmdIndex, bytes32 cmd, bool success, bytes data);
event VMInternalCall(uint256 cmdIndex, bytes32 cmd);
event VMReturn(bool success, bytes data);
event LogStatement(
uint256 indexed statementId,
bytes encoded
);
error ExecutionFailed(
uint256 command_index,
address target,
string message
);
library VMOpcodes {
using CommandBuilder for VMState;
using Memory for VMState;
using VMOpcodes for VMState;
// Transient storage slots used by the VM
uint256 internal constant EXPECTED_CALLBACK_SLOT = 0;
uint256 internal constant CALLDATA_DATA_SLOT = 1;
function getExpectedCallbackAddress() internal returns (address) {
return address(uint160(uint256(TransientStorage.tread(EXPECTED_CALLBACK_SLOT))));
}
function getCalldataOffset() internal returns (uint256) {
return uint256(TransientStorage.tread(CALLDATA_DATA_SLOT));
}
uint256 constant FLAG_CT_DELEGATECALL = 0x00;
uint256 constant FLAG_CT_CALL = 0x01;
uint256 constant FLAG_CT_STATICCALL = 0x02;
uint256 constant FLAG_CT_VALUECALL = 0x03;
uint256 constant FLAG_CT_MASK = 0x03;
uint256 constant FLAG_EXTENDED_COMMAND = 0x80;
uint256 constant FLAG_TUPLE_RETURN = 0x40;
uint256 constant FLAG_INTERNAL_CMD = 0x20;
uint256 constant SHORT_COMMAND_FILL = 0x000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 constant FLAG_INTERPRET = 0x1;
uint256 constant TX_FLAGS_MASK = 0xff;
uint256 constant TX_LEVEL_MASK = 0xff00;
function opEncodeCallback(
VMState memory vmstate,
bytes32 indices,
uint256 outputSlot
) internal {
TransientStorage.twrite(EXPECTED_CALLBACK_SLOT, vmstate.readUint256(uint8(indices[2])));
TransientStorage.twrite(CALLDATA_DATA_SLOT, vmstate.readUint256(uint8(indices[3])));
bytes memory rawBuff = vmstate.data[
uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK
];
bytes32[] memory commands;
assembly {
commands := add(rawBuff, 32)
}
vmstate.meta[outputSlot] = DataTag.DEFAULT;
uint256 newFlags = ((1 + (vmstate.flags >> 8)) << 8) | (vmstate.flags & TX_FLAGS_MASK);
bytes memory encoded = abi.encode(0, newFlags, commands, vmstate.meta, vmstate.data);
assembly {
mstore(add(encoded, 32), sub(mload(encoded), 32))
// adjust offsets as we inserted a 32 byte length field
mstore(add(encoded, 96), sub(mload(add(encoded, 96)), 32))
mstore(add(encoded, 128), sub(mload(add(encoded, 128)), 32))
mstore(add(encoded, 160), sub(mload(add(encoded, 160)), 32))
}
vmstate.data[outputSlot] = encoded;
}
function opAssert(
VMState memory state,
bytes32 indices
) internal pure returns (bool success, bytes memory outdata) {
if (state.readUint256(uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK) == 1) {
return (true, "");
}
string memory data = indices[1] != 0xff ? string(state.readBuffer(
uint8(indices[1]) & CommandBuilder.IDX_VALUE_MASK
)) : "Assertion failed";
return (false, bytes(data));
}
function opUnary(
VMState memory state,
bytes32 indices,
uint256 out,
uint256 op
) internal pure {
uint256 a = state.readUint256(uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK);
uint256 b = MathOpCodes.unaryOp(op, a);
state.writeWord(out, b);
}
function opBinary(
VMState memory state,
bytes32 indices,
uint256 out,
uint256 op
) internal pure {
uint256 a = Memory.readUint256(state, uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK);
uint256 b = Memory.readUint256(state, uint8(indices[1]) & CommandBuilder.IDX_VALUE_MASK);
uint256 c = MathOpCodes.binaryOp(op, a, b);
state.writeWord(out, c);
}
function opLog(
VMState memory state,
bytes32 indices,
uint256 logStatement
) internal {
bytes32 format = state.readValue(
uint8(indices[0])
);
uint256 args = 0;
uint256 buffers = 0;
for(uint256 i = 1; i < 32; i++) {
if (uint8(indices[i]) == 0xff) break;
args += 1;
uint8 vformat = uint8(format[i - 1]);
if ((vformat & 8) != 0) {
buffers += 1;
}
}
bytes32[] memory values = new bytes32[](args);
bytes[] memory outBuffers = new bytes[](buffers);
buffers = 0;
for(uint256 i = 0; i < 32; i++) {
uint8 vformat = uint8(format[i]);
uint8 idx = uint8(indices[i + 1]);
if (vformat == 0xff||idx == 0xff) break;
if (vformat == 0) {
values[i] = bytes32(state.readUint256(
idx & CommandBuilder.IDX_VALUE_MASK
));
continue;
}
if ((vformat & 8) == 0) {
values[i] = bytes32(uint256(idx));
continue;
}
values[i] = bytes32(buffers);
bytes memory buff = state.readBuffer(
idx & CommandBuilder.IDX_VALUE_MASK
);
outBuffers[buffers] = buff;
buffers += 1;
}
emit LogStatement(
logStatement & 0xffffffff,
abi.encode(values, outBuffers)
);
}
function opEvent(
VMState memory state,
bytes32 indices,
uint256 topics
) internal {
if (topics == 0) {
bytes memory data = state.makeTuple(indices);
assembly {
log0(add(data, 32), mload(data))
}
} else if (topics == 1) {
bytes32 topic = state.readValue(uint8(indices[0]));
bytes memory data = state.makeTuple(bytes32((uint256(indices) << 8)|0xff));
assembly {
log1(add(data, 32), mload(data), topic)
}
} else if (topics == 2) {
bytes32 topic1 = state.readValue(uint8(indices[0]));
bytes32 topic2 = state.readValue(uint8(indices[1]));
bytes memory data = state.makeTuple(bytes32((uint256(indices) << 16) | 0xffff));
assembly {
log2(add(data, 32), mload(data), topic1, topic2)
}
} else if (topics == 3) {
bytes32 topic1 = state.readValue(uint8(indices[0]));
bytes32 topic2 = state.readValue(uint8(indices[1]));
bytes32 topic3 = state.readValue(uint8(indices[2]));
bytes memory data = state.makeTuple(bytes32((uint256(indices) << 24) | 0xffffff));
assembly {
log3(add(data, 32), mload(data), topic1, topic2, topic3)
}
} else if (topics == 4) {
bytes32 topic1 = state.readValue(uint8(indices[0]));
bytes32 topic2 = state.readValue(uint8(indices[1]));
bytes32 topic3 = state.readValue(uint8(indices[2]));
bytes32 topic4 = state.readValue(uint8(indices[3]));
bytes memory data = state.makeTuple(bytes32((uint256(indices) << 32) | 0xffffffff));
assembly {
log4(add(data, 32), mload(data), topic1, topic2, topic3, topic4)
}
} else {
revert("Invalid number of topics");
}
}
function opReturn(
VMState memory vmstate,
bytes32 indices
) internal {
bytes memory returnData = vmstate.readBuffer(
uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK
);
if ((vmstate.flags & FLAG_INTERPRET) == FLAG_INTERPRET) {
emit VMReturn(true, returnData);
}
assembly {
return(add(returnData, 32), mload(returnData))
}
}
function opMemoryLoad(
VMState memory vmstate,
bytes32 indices,
bytes32 command,
uint256 outputSlot,
uint256 flags
) internal {
if (outputSlot == 127) {
return;
}
bytes memory outData = vmstate.readMemory(
indices
);
if (uint8(bytes1(command << 88)) & CommandBuilder.IDX_VARIABLE_LENGTH == 0) {
bytes memory outSlot = vmstate.getBufferForSlot(outputSlot, 32);
assembly {
mstore(outSlot, 32)
mstore(add(outSlot, 32), mload(add(outData, 32)))
}
vmstate.meta[outputSlot] = DataTag.DEFAULT;
} else {
if (flags & FLAG_TUPLE_RETURN != 0) {
vmstate.meta[outputSlot] = DataTag.TUPLE;
} else {
vmstate.meta[outputSlot] = DataTag.DEFAULT;
}
vmstate.data[outputSlot] = outData;
}
}
function evaluateInternalOp(
VMState memory vmstate,
VMOutput memory out,
bytes32 command,
uint256 flags,
bytes32 indices,
uint256 i
) internal returns (bool writeOutputs) {
uint256 outputSlot = uint8(bytes1(command << 88)) & CommandBuilder.IDX_VALUE_MASK;
if ((vmstate.flags & FLAG_INTERPRET) == FLAG_INTERPRET) {
emit VMInternalCall((vmstate.flags & TX_LEVEL_MASK) | i, command);
}
uint256 cmd;
assembly {
// shift the 4 most significant bytes to the right
cmd := shr(224, command)
}
if (cmd == 0) { // read calldata opcode
if (outputSlot == 127) {
return true;
}
out.outdata = vmstate.opCalldataRead(
indices,
uint8(bytes1(command << 88))
);
out.success = out.outdata.length != 0;
if (out.outdata.length == 32) {
return true;
}
return false;
} else if (cmd == 1) { // tuple opcode
out.outdata = vmstate.makeTuple(
indices
);
out.success = out.outdata.length != 0 ? true : false;
return false;
} else if (cmd == 2) {
vmstate.opMemoryLoad(indices, command, outputSlot, flags);
} else if (cmd == 3) {
vmstate.opBinary(
indices,
outputSlot,
uint256(command)
);
} else if (cmd == 4) {
(out.success, out.outdata) = opAssert(
vmstate,
indices
);
return false;
} else if (cmd == 5) {
vmstate.opLog(
indices,
uint256(command)
);
} else if (cmd == 7) {
vmstate.opUnary(
indices,
outputSlot,
uint256(command)
);
} else if (cmd == 8) {
vmstate.opEvent(
indices,
uint256(command) & 0xff
);
} else if (cmd == 9) {
vmstate.opReturn(indices);
} else if (cmd == 10) {
if (outputSlot == 127) {
return true;
}
vmstate.data[outputSlot] = vmstate.data[uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK];
if (flags & FLAG_TUPLE_RETURN != 0) {
vmstate.meta[outputSlot] = DataTag.TUPLE;
} else {
vmstate.meta[outputSlot] = DataTag.DEFAULT;
}
} else if (cmd == 11) { // encode callback
vmstate.opEncodeCallback(indices, outputSlot);
} else if (cmd == 12) { // mstore
vmstate.opMStore(
indices,
outputSlot
);
} else if (cmd == 16) { // LEN
vmstate.writeWord(outputSlot, vmstate.readUint256((uint8(indices[0]) & CommandBuilder.IDX_VALUE_MASK)));
} else if (cmd >= 31) {
bytes memory outputslot = vmstate.getBufferForSlot(outputSlot, 32);
cmd = cmd & 31;
bytes32 firstArg = indices[0] != 0xff ? vmstate.readValue(
uint8(indices[0])
) : bytes32(0);
assembly {
switch cmd
case 0 { mstore(add(outputslot, 32), number()) }
case 1 { mstore(add(outputslot, 32), address()) }
case 2 { mstore(add(outputslot, 32), caller()) }
case 3 { mstore(add(outputslot, 32), gas()) }
case 4 { mstore(add(outputslot, 32), selfbalance()) }
case 5 { mstore(add(outputslot, 32), balance(firstArg)) }
case 6 { mstore(add(outputslot, 32), chainid()) }
case 7 { mstore(add(outputslot, 32), callvalue()) }
case 8 { mstore(add(outputslot, 32), timestamp()) }
case 9 { mstore(add(outputslot, 32), origin()) }
case 10 { mstore(add(outputslot, 32), coinbase()) }
default { revert(0, 0) }
}
} else {
out.success = false;
out.outdata = abi.encodePacked("Invalid internal command");
return false;
}
return true;
}
}
abstract contract VM {
using CommandBuilder for VMState;
using Memory for VMState;
using VMOpcodes for VMState;
// Transient storage slots used by the VM
uint256 constant FLAG_CT_DELEGATECALL = 0x00;
uint256 constant FLAG_CT_CALL = 0x01;
uint256 constant FLAG_CT_STATICCALL = 0x02;
uint256 constant FLAG_CT_VALUECALL = 0x03;
uint256 constant FLAG_CT_MASK = 0x03;
uint256 constant FLAG_EXTENDED_COMMAND = 0x80;
uint256 constant FLAG_TUPLE_RETURN = 0x40;
uint256 constant FLAG_INTERNAL_CMD = 0x20;
uint256 constant SHORT_COMMAND_FILL = 0x000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 constant FLAG_INTERPRET = 0x1;
uint256 constant TX_FLAGS_MASK = 0xff;
uint256 constant TX_LEVEL_MASK = 0xff00;
/** Must be added to implementation contract fallback to enable generic callbacks */
function fallbackHook() internal {
address constraint = VMOpcodes.getExpectedCallbackAddress();
require(msg.sender == constraint, "Invalid callback");
uint256 calldataOffset = VMOpcodes.getCalldataOffset();
uint256 calldataSize = 0;
assembly {
calldataOffset := add(calldataload(calldataOffset), 4)
calldataSize := calldataload(calldataOffset)
}
bytes memory data = new bytes(calldataSize);
assembly {
calldatacopy(add(data, 32), add(calldataOffset, 32), calldataSize)
}
(
uint256 flags,
bytes32[] memory commands,
DataTag[] memory meta,
bytes[] memory state
) = abi.decode(data, (uint256, bytes32[], DataTag[], bytes[]));
VMState memory vmstate = VMState(
meta,
state,
flags
);
_execute(
vmstate,
commands
);
}
function _execute(
VMState memory vmstate,
bytes32[] memory commands
) internal returns (VMOutput memory out) {
uint256 commandsLength = commands.length;
for (uint256 i; i < commandsLength;) {
bytes32 command = commands[i];
uint256 flags = uint256(uint8(bytes1(command << 32)));
bytes32 indices;
if (flags & FLAG_EXTENDED_COMMAND != 0) {
indices = commands[++i];
} else {
indices = bytes32(uint256(command << 40) | SHORT_COMMAND_FILL);
}
if (flags & FLAG_INTERNAL_CMD != 0) {
if (vmstate.evaluateInternalOp(out, command, flags, indices, i)) {
i++;
continue;
}
} else {
bytes memory inputs = vmstate.buildInputs(
bytes4(command),
indices
);
if ((vmstate.flags & FLAG_INTERPRET) == FLAG_INTERPRET) {
emit VMCall(
(vmstate.flags & TX_LEVEL_MASK) | i,
commands[i],
address(uint160(uint256(command))),
inputs,
flags & FLAG_CT_MASK
);
}
if ((uint256(command) & 0x00ffffffffffffffffffffffffffffffffffffffff) < 127) {
bytes memory statevar = vmstate.data[uint256(command) & 0xff];
assembly {
command := or(and(command, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000), mload(add(statevar, 32)))
}
}
if (flags & FLAG_CT_MASK == FLAG_CT_DELEGATECALL) {
(out.success, out.outdata) = address(uint160(uint256(command))).delegatecall( // target
// inputs
inputs
);
} else if (flags & FLAG_CT_MASK == FLAG_CT_CALL) {
(out.success, out.outdata) = address(uint160(uint256(command))).call( // target
// inputs
inputs
);
} else if (flags & FLAG_CT_MASK == FLAG_CT_STATICCALL) {
(out.success, out.outdata) = address(uint160(uint256(command))).staticcall( // target
// inputs
inputs
);
} else if (flags & FLAG_CT_MASK == FLAG_CT_VALUECALL) {
uint256 calleth;
bytes memory v = vmstate.data[uint8(bytes1(indices))];
require(v.length == 32, "_execute: value call has no value indicated.");
assembly {
calleth := mload(add(v, 0x20))
}
(out.success, out.outdata) = address(uint160(uint256(command))).call{ // target
value: calleth
}(
// inputs
vmstate.buildInputs(
//selector
bytes4(command),
bytes32(uint256(indices << 8) | CommandBuilder.IDX_END_OF_ARGS)
)
);
} else {
revert("Invalid calltype");
}
if ((vmstate.flags & FLAG_INTERPRET) == FLAG_INTERPRET) {
emit VMCallReturn((vmstate.flags & TX_LEVEL_MASK) | i, commands[i], out.success, out.outdata);
}
}
if (!out.success) {
if ((vmstate.flags & FLAG_INTERPRET) == FLAG_INTERPRET) {
emit VMException(
(vmstate.flags & TX_LEVEL_MASK) | i,
out.outdata
);
return out;
}
if (out.outdata.length > 0) {
bytes memory outdata = out.outdata;
assembly {
outdata := add(outdata, 68)
}
}
revert(out.outdata.length > 0 ? string(out.outdata) : "Unknown");
}
if (flags & FLAG_TUPLE_RETURN != 0) {
vmstate.writeTuple(bytes1(command << 88), out.outdata);
} else {
vmstate = vmstate.writeOutputs(bytes1(command << 88), out.outdata);
}
i++;
}
if ((vmstate.flags & FLAG_INTERPRET) == FLAG_INTERPRET) {
emit VMReturn(out.success, out.outdata);
}
return out;
}
}
VMState.sol 19 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
enum DataTag {
DEFAULT,
TUPLE
}
struct VMState {
DataTag[] meta;
bytes[] data;
uint256 flags;
}
struct VMOutput {
bool success;
bytes outdata;
}
Write Contract 1 functions
These functions modify contract state and require a wallet transaction to execute.
execute 0x93c717ce
bytes32[] commands
bytes[] state
uint256 flags
returns: tuple
Token Balances (3)
View Transfers →Recent Transactions
No transactions found for this address