Address Contract Partially Verified
Address
0xb634316E06cC0B358437CbadD4dC94F1D3a92B3b
Balance
0 ETH
Nonce
1
Code Size
6386 bytes
Creator
0x2757AE02...e58e at tx 0x484843f4...236091
Indexed Transactions
0
Contract Bytecode
6386 bytes
0x60806040526004361061010b5760003560e01c80638f4e6f371161009a578063d0adcdf611610061578063d0adcdf614610316578063de792d5f14610336578063ec58f4b814610363578063f0f4426014610383578063f39c38a0146103a357005b80638f4e6f37146102765780638fd57b92146102965780639cd38be5146102b65780639ed6c6f6146102d6578063ab033ea9146102f657005b806351160630116100de57806351160630146101ae57806357f58d98146101e65780635aa6e6751461021657806361d027b31461023657806366f88f821461025657005b8062b8ff9214610114578063238efcbc1461013457806349d6e212146101495780634c8541261461018e57005b3661011257005b005b34801561012057600080fd5b5061011261012f36600461132f565b6103c3565b34801561014057600080fd5b50610112610406565b34801561015557600080fd5b5061017961016436600461137a565b60046020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561019a57600080fd5b506101126101a9366004611397565b61047b565b3480156101ba57600080fd5b506003546101ce906001600160a01b031681565b6040516001600160a01b039091168152602001610185565b3480156101f257600080fd5b5061017961020136600461137a565b60056020526000908152604090205460ff1681565b34801561022257600080fd5b506000546101ce906001600160a01b031681565b34801561024257600080fd5b506002546101ce906001600160a01b031681565b34801561026257600080fd5b5061011261027136600461137a565b6104e0565b34801561028257600080fd5b5061011261029136600461137a565b610562565b3480156102a257600080fd5b506101126102b136600461137a565b610600565b3480156102c257600080fd5b506101126102d1366004611397565b61067b565b3480156102e257600080fd5b506101126102f136600461141c565b61068a565b34801561030257600080fd5b5061011261031136600461137a565b610864565b34801561032257600080fd5b5061011261033136600461137a565b6108b0565b34801561034257600080fd5b5061035661035136600461151b565b610948565b6040516101859190611688565b34801561036f57600080fd5b5061011261037e36600461137a565b6109f3565b34801561038f57600080fd5b5061011261039e36600461137a565b610a71565b3480156103af57600080fd5b506001546101ce906001600160a01b031681565b6000546001600160a01b031633146103f65760405162461bcd60e51b81526004016103ed906116ea565b60405180910390fd5b610401838383610ae9565b505050565b6001546001600160a01b0316331461041d57600080fd5b60018054600080546001600160a01b0383166001600160a01b031991821681179092559091169091556040519081527f17fdeaa3d89b13aa2b63d35b4629f020be603156d5afcf4aba89bfa93d5f579d9060200160405180910390a1565b6001600160a01b03821661048e57600080fd5b6001600160a01b0381166104a157600080fd5b6040516001600160a01b03808316919084169033907f39e31092deb8f976532f8f405a66c2a1f574b4494ba37cbc2915c1914a9689f290600090a45050565b6000546001600160a01b0316331461050a5760405162461bcd60e51b81526004016103ed906116ea565b6001600160a01b038116600081815260046020908152604091829020805460ff1916905590519182527f74cbb97aad2128ac02cf33c1dd8791a60aae9afab06f3a411169bdae081277c591015b60405180910390a150565b6000546001600160a01b0316331461058c5760405162461bcd60e51b81526004016103ed906116ea565b6001600160a01b03811660009081526004602052604090205460ff16156105b257600080fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f1fa4026b4d339f83c1501efed0d8a25130bf25d6e1b2b0a2c48c8225b2d0fb1e90602001610557565b6000546001600160a01b0316331461062a5760405162461bcd60e51b81526004016103ed906116ea565b6001600160a01b038116600081815260056020908152604091829020805460ff1916905590519182527f736584b2af2b5be32a90fa808de47de356f4e8d00b0c131f3e3c61240b5d71909101610557565b610686338383610ae9565b5050565b8281811461069757600080fd5b60005b8181101561085c5760008686838181106106b6576106b661170f565b90506020020160208101906106cb919061137a565b6001600160a01b03160361077d57600254731b45a86e58b97df309bae0e6c4bbcd40f5a23d5490637c4368c1906001600160a01b03168686858181106107135761071361170f565b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160006040518083038186803b15801561076057600080fd5b505af4158015610774573d6000803e3d6000fd5b5050505061084a565b731b45a86e58b97df309bae0e6c4bbcd40f5a23d5463d1660f998787848181106107a9576107a961170f565b90506020020160208101906107be919061137a565b6002546001600160a01b03168787868181106107dc576107dc61170f565b6040516001600160e01b031960e088901b1681526001600160a01b0395861660048201529490931660248501525060209091020135604482015260640160006040518083038186803b15801561083157600080fd5b505af4158015610845573d6000803e3d6000fd5b505050505b806108548161173b565b91505061069a565b505050505050565b6000546001600160a01b0316331461088e5760405162461bcd60e51b81526004016103ed906116ea565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146108da5760405162461bcd60e51b81526004016103ed906116ea565b6003546001600160a01b038083169116036108f457600080fd5b6001600160a01b038116600081815260046020908152604091829020805460ff1916600117905590519182527fb43754e0033076ed886a3bee063313d9f0da4612cd15041451f9ccf4108205bd9101610557565b6003546060906001600160a01b03163314801561097457503260009081526005602052604090205460ff165b806109a457506003546001600160a01b031633148015906109a457503360009081526004602052604090205460ff165b6109de5760405162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b60448201526064016103ed565b6109e9848484610b38565b90505b9392505050565b6000546001600160a01b03163314610a1d5760405162461bcd60e51b81526004016103ed906116ea565b6001600160a01b038116600081815260056020908152604091829020805460ff1916600117905590519182527f68f4df5a91ac3c3a2468604a418ba454518d42eb6fcedccca0c00bd1129bcc7f9101610557565b6000546001600160a01b03163314610a9b5760405162461bcd60e51b81526004016103ed906116ea565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fa6df481f77da1f4c92eb330341e03585d46106fcf522f8e6b6b2afbea56eefdc90602001610557565b806001600160a01b0316826001600160a01b0316846001600160a01b03167fb670ba64017b695a17160f17252635c78b7e4b57d1efcf9a6968b9c03e7b596660405160405180910390a4505050565b606060008080808487825b81811015610eee578a8a82818110610b5d57610b5d61170f565b90506020020135965060d887901c60001c60ff16955060408616600014610ba9578a8a610b898361173b565b925082818110610b9b57610b9b61170f565b905060200201359450610bba565b602887901b6001600160d01b031794505b60038616610c2f576001600160a01b038716610bd78a8988610efd565b604051610be49190611754565b600060405180830381855af49150503d8060008114610c1f576040519150601f19603f3d011682016040523d82523d6000602084013e610c24565b606091505b509094509250610e52565b60016003871603610c99576001600160a01b038716610c4f8a8988610efd565b604051610c5c9190611754565b6000604051808303816000865af19150503d8060008114610c1f576040519150601f19603f3d011682016040523d82523d6000602084013e610c24565b60026003871603610d01576001600160a01b038716610cb98a8988610efd565b604051610cc69190611754565b600060405180830381855afa9150503d8060008114610c1f576040519150601f19603f3d011682016040523d82523d6000602084013e610c24565b600380871603610e17576000808a8760f81c60ff1681518110610d2657610d2661170f565b602002602001015190508051602014610d965760405162461bcd60e51b815260206004820152602c60248201527f5f657865637574653a2076616c75652063616c6c20686173206e6f2076616c7560448201526b329034b73234b1b0ba32b21760a11b60648201526084016103ed565b602081015191506001600160a01b03891682610dba8d8c60088c901b60ff17610efd565b604051610dc79190611754565b60006040518083038185875af1925050503d8060008114610e04576040519150601f19603f3d011682016040523d82523d6000602084013e610e09565b606091505b509096509450610e52915050565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c7479706560801b60448201526064016103ed565b83610eb757825115610e65576044830192505b60008760001c6000855111610e9957604051806040016040528060078152602001662ab735b737bbb760c91b815250610e9b565b845b60405163ef3dcb2f60e01b81526004016103ed93929190611770565b6080861615610ed457610ecf89605889901b856110fd565b610ee6565b610ee389605889901b856111a5565b98505b600101610b43565b50969998505050505050505050565b606060008060005b6020811015610f3c57848160208110610f2057610f2061170f565b1a915060fe19820115610f3c5760209290920191600101610f05565b5060408051808201909152602081018690529250600460006060815b60208110156110ee57878160208110610f7357610f7361170f565b1a945060fe198501156110ee57608085161561109f5760fe850361102f57601f19605f85011687016040526024838801018690528151602090940193600003610fd95789604051602001610fc79190611688565b60405160208183030381529060405291505b8151603f9401938401601f1916870160405261101082602089610ffd8a60046117a3565b6020875161100b91906117bc565b6112fd565b6020825161101e91906117bc565b61102890876117a3565b95506110df565b60008a607f8716815181106110465761104661170f565b6020908102919091018101518051868b016024018a9052968701605f8101601f19168b016040529091019590915061108c8260008b6110868c60046117a3565b856112fd565b61109681896117a3565b975050506110df565b60008a607f8716815181106110b6576110b661170f565b6020908102919091018101518051603f9701968701601f19168a01604052015184890160240152505b60209290920191600101610f58565b50505083525090949350505050565b60f882901c60fe1981016111115750505050565b60008251602061112191906117a3565b67ffffffffffffffff81111561113957611139611488565b6040519080825280601f01601f191660200182016040528015611163576020820181803683370190505b5085607f8416815181106111795761117961170f565b60200260200101819052905061119583600083602087516112fd565b8251806020830152505050505050565b606060f883901c60fe1981016111be57849150506109ec565b60808116156112705760fe81036111ea57828060200190518101906111e391906117cf565b94506112f4565b6020838101519081146112525760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015269287661726961626c652960b01b60648201526084016103ed565b508251601f19016020848101918252607f83168102870101526112f4565b82516020146112d25760405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015267287374617469632960c01b60648201526084016103ed565b8285607f8316815181106112e8576112e861170f565b60200260200101819052505b50929392505050565b808260208501018286602089010160045afa505050505050565b6001600160a01b038116811461132c57600080fd5b50565b60008060006060848603121561134457600080fd5b833561134f81611317565b9250602084013561135f81611317565b9150604084013561136f81611317565b809150509250925092565b60006020828403121561138c57600080fd5b81356109ec81611317565b600080604083850312156113aa57600080fd5b82356113b581611317565b915060208301356113c581611317565b809150509250929050565b60008083601f8401126113e257600080fd5b50813567ffffffffffffffff8111156113fa57600080fd5b6020830191508360208260051b850101111561141557600080fd5b9250929050565b6000806000806040858703121561143257600080fd5b843567ffffffffffffffff8082111561144a57600080fd5b611456888389016113d0565b9096509450602087013591508082111561146f57600080fd5b5061147c878288016113d0565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114c7576114c7611488565b604052919050565b600067ffffffffffffffff8211156114e9576114e9611488565b5060051b60200190565b600067ffffffffffffffff82111561150d5761150d611488565b50601f01601f191660200190565b6000806000604080858703121561153157600080fd5b843567ffffffffffffffff8082111561154957600080fd5b611555888389016113d0565b909650945060209150868201358181111561156f57600080fd5b8701601f8101891361158057600080fd5b803561159361158e826114cf565b61149e565b81815260059190911b8201840190848101908b8311156115b257600080fd5b8584015b83811015611626578035868111156115ce5760008081fd5b8501603f81018e136115e05760008081fd5b878101356115f061158e826114f3565b8181528f8b8385010111156116055760008081fd5b818b84018b83013760009181018a01919091528452509186019186016115b6565b50809750505050505050509250925092565b60005b8381101561165357818101518382015260200161163b565b50506000910152565b60008151808452611674816020860160208601611638565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156116dd57603f198886030184526116cb85835161165c565b945092850192908501906001016116af565b5092979650505050505050565b6020808252600b908201526a21676f7665726e616e636560a81b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161174d5761174d611725565b5060010190565b60008251611766818460208701611638565b9190910192915050565b8381526001600160a01b038316602082015260606040820181905260009061179a9083018461165c565b95945050505050565b808201808211156117b6576117b6611725565b92915050565b818103818111156117b6576117b6611725565b600060208083850312156117e257600080fd5b825167ffffffffffffffff808211156117fa57600080fd5b818501915085601f83011261180e57600080fd5b815161181c61158e826114cf565b81815260059190911b8301840190848101908883111561183b57600080fd5b8585015b838110156118af578051858111156118575760008081fd5b8601603f81018b136118695760008081fd5b87810151604061187b61158e836114f3565b8281528d828486010111156118905760008081fd5b61189f838c8301848701611638565b865250505091860191860161183f565b509897505050505050505056fea2646970667358221220bc488897086574fb93bc838a9bd5eb177f591f592d440e94ff6c9c70abfc7a2964736f6c63430008110033
Verified Source Code Partial Match
Compiler: v0.8.17+commit.8df45f5f
EVM: london
Optimization: Yes (200 runs)
CommandBuilder.sol 179 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
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(
bytes[] memory state,
bytes4 selector,
bytes32 indices
) internal view returns (bytes memory ret) {
uint256 free; // Pointer to first free byte in tail part of message
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;
unchecked{free += 32;}
unchecked{++i;}
}
// Encode it
uint256 bytesWritten;
assembly {
ret := mload(0x40)
bytesWritten := add(bytesWritten, 4)
mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
mstore(add(ret, 32), selector)
}
uint256 count = 0;
bytes memory stateData; // Optionally encode the current state if the call requires it
for (uint256 i; i < 32;) {
idx = uint8(indices[i]);
if (idx == IDX_END_OF_ARGS) break;
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_USE_STATE) {
assembly {
bytesWritten := add(bytesWritten, 32)
mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
mstore(add(add(ret, 36), count), free)
}
if (stateData.length == 0) {
stateData = abi.encode(state);
}
assembly {
bytesWritten := add(bytesWritten, mload(stateData))
mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
}
memcpy(stateData, 32, ret, free + 4, stateData.length - 32);
free += stateData.length - 32;
} else {
bytes memory stateVar = state[idx & IDX_VALUE_MASK];
uint256 arglen = stateVar.length;
// Variable length data; put a pointer in the slot and write the data at the end
assembly {
bytesWritten := add(bytesWritten, 32)
mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
mstore(add(add(ret, 36), count), free)
}
assembly {
bytesWritten := add(bytesWritten, arglen)
mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
}
memcpy(
stateVar,
0,
ret,
free + 4,
arglen
);
free += arglen;
}
} else {
// Fixed length data; write it directly
bytes memory stateVar = state[idx & IDX_VALUE_MASK];
assembly {
bytesWritten := add(bytesWritten, mload(stateVar))
mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
mstore(add(add(ret, 36), count), mload(add(stateVar, 32)))
}
}
unchecked{count += 32;}
unchecked{++i;}
}
assembly {
mstore(ret, bytesWritten)
}
}
function writeOutputs(
bytes[] memory state,
bytes1 index,
bytes memory output
) internal pure returns (bytes[] 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, (bytes[]));
} 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)"
);
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(state, 32), mul(and(idx, IDX_VALUE_MASK), 32)),
add(output, 32)
)
}
}
} else {
// Single word
require(
output.length == 32,
"Only one return value permitted (static)"
);
state[idx & IDX_VALUE_MASK] = output;
}
return state;
}
function writeTuple(
bytes[] 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[idx & IDX_VALUE_MASK] = new bytes(output.length + 32);
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
)
)
}
}
}
TradeHandler.sol 189 lines
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.17;
import "./VM.sol";
import "./TradeHandlerHelper.sol";
/**
@title Trade Handler
@author yearn.finance
@notice TradeHandler is in charge of tracking which strategy wants to do certain
trade. The strategy registers what they have and what they want and wait for an
async trade. TradeHandler trades are executed by mechs through a weiroll VM.
*/
contract TradeHandler is VM {
address payable public governance;
address payable public pendingGovernance;
// Treasury multisig for sweeps
address payable public treasury;
// COW protocol settlement contract address.
address public settlement;
// Mechs are addresses other than `settlement` that are authorized to
// to call `execute()`
mapping(address => bool) public mechs;
// Solvers are EOAs authorised by COW protocol's settlement contract to
// settle batches won at an auction
mapping(address => bool) public solvers;
event UpdatedSettlement(address settlement);
event UpdatedTreasury(address treasury);
event UpdatedGovernance(address governance);
event AddedMech(address mech);
event RemovedMech(address mech);
event AddedSolver(address solver);
event RemovedSolver(address solver);
event TradeEnabled(
address indexed seller,
address indexed tokenIn,
address indexed tokenOut
);
event TradeDisabled(
address indexed seller,
address indexed tokenIn,
address indexed tokenOut
);
modifier onlyGovernance() {
require(msg.sender == governance, "!governance");
_;
}
// The settlement contract must be authorized to call `execute()`, but additional
// safeguards are needed because solvers other than Seasolver are also authorized
// to call settlement.settle().
modifier onlyAuthorized() {
require(
((msg.sender == settlement) && solvers[tx.origin]) ||
((msg.sender != settlement && mechs[msg.sender])),
"!authorized"
);
_;
}
constructor(address payable _governance) {
governance = _governance;
treasury = _governance;
mechs[_governance] = true;
}
function setGovernance(address payable _governance)
external
onlyGovernance
{
pendingGovernance = _governance;
}
function setTreasury(address payable _treasury) external onlyGovernance {
treasury = _treasury;
emit UpdatedTreasury(_treasury);
}
function acceptGovernance() external {
require(msg.sender == pendingGovernance);
governance = pendingGovernance;
delete pendingGovernance;
emit UpdatedGovernance(governance);
}
function setSettlement(address _settlement) external onlyGovernance {
// Settlement can't be a mech.
require(!mechs[_settlement]);
settlement = _settlement;
emit UpdatedSettlement(_settlement);
}
function addMech(address _mech) external onlyGovernance {
// Settlement can't be set as mech as that would grant
// other solvers power to execute.
require(settlement != _mech);
mechs[_mech] = true;
emit AddedMech(_mech);
}
function removeMech(address _mech) external onlyGovernance {
delete mechs[_mech];
emit RemovedMech(_mech);
}
function addSolver(address _solver) external onlyGovernance {
solvers[_solver] = true;
emit AddedSolver(_solver);
}
function removeSolver(address _solver) external onlyGovernance {
delete solvers[_solver];
emit RemovedSolver(_solver);
}
function enable(address _tokenIn, address _tokenOut) external {
require(_tokenIn != address(0));
require(_tokenOut != address(0));
emit TradeEnabled(msg.sender, _tokenIn, _tokenOut);
}
function disable(address _tokenIn, address _tokenOut) external {
_disable(msg.sender, _tokenIn, _tokenOut);
}
function disableByAdmin(
address _strategy,
address _tokenIn,
address _tokenOut
) external onlyGovernance {
_disable(_strategy, _tokenIn, _tokenOut);
}
function _disable(
address _strategy,
address _tokenIn,
address _tokenOut
) internal {
emit TradeDisabled(_strategy, _tokenIn, _tokenOut);
}
function execute(bytes32[] calldata commands, bytes[] memory state)
external
onlyAuthorized
returns (bytes[] memory)
{
return _execute(commands, state);
}
function sweep(address[] calldata _tokens, uint256[] calldata _amounts)
external
{
uint256 _size = _tokens.length;
require(_size == _amounts.length);
for (uint256 i = 0; i < _size; i++) {
if (_tokens[i] == address(0)) {
// Native ETH
TradeHandlerHelper.safeTransferETH(treasury, _amounts[i]);
} else {
// ERC20s
TradeHandlerHelper.safeTransfer(
_tokens[i],
treasury,
_amounts[i]
);
}
}
}
// `fallback` is called when msg.data is not empty
fallback() external payable {}
// `receive` is called when msg.data is empty
receive() external payable {}
}
TradeHandlerHelper.sol 217 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
library TradeHandlerHelper {
function insertElement(
bytes calldata tuple,
uint256 index,
bytes32 element,
bool returnRaw
) public pure returns (bytes memory newTuple) {
uint256 byteIndex;
unchecked {
byteIndex = index * 32;
}
require(byteIndex <= tuple.length);
newTuple = bytes.concat(tuple[:byteIndex], element, tuple[byteIndex:]);
if (returnRaw) {
assembly {
return(add(newTuple, 32), tuple.length)
}
}
}
function replaceElement(
bytes calldata tuple,
uint256 index,
bytes32 element,
bool returnRaw
) public pure returns (bytes memory newTuple) {
uint256 byteIndex;
unchecked {
byteIndex = index * 32;
require(tuple.length >= 32 && byteIndex <= tuple.length - 32);
newTuple = bytes.concat(
tuple[:byteIndex],
element,
tuple[byteIndex + 32:]
);
}
if (returnRaw) {
assembly {
return(add(newTuple, 32), tuple.length)
}
}
}
function getElement(bytes memory tuple, uint256 index)
public
pure
returns (bytes32)
{
assembly {
return(add(tuple, mul(add(index, 1), 32)), 32)
}
}
function power(uint256 a, uint256 b) public pure returns (uint256) {
return a**b;
}
function sum(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
function subtract(uint256 a, uint256 b) public pure returns (uint256) {
return a - b;
}
function multiply(uint256 a, uint256 b) public pure returns (uint256) {
return a * b;
}
function divide(uint256 a, uint256 b) public pure returns (uint256) {
return a / b;
}
/// @dev Wrapper around a call to the ERC20 function `transfer` that reverts
/// also when the token returns `false`.
function safeTransfer(
address token,
address to,
uint256 value
) external {
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(
freeMemoryPointer,
0xa9059cbb00000000000000000000000000000000000000000000000000000000
)
mstore(
add(freeMemoryPointer, 4),
and(to, 0xffffffffffffffffffffffffffffffffffffffff)
)
mstore(add(freeMemoryPointer, 36), value)
if iszero(call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
require(getLastTransferResult(token), "!transfer");
}
/// @dev Wrapper around a call to the ERC20 function `transferFrom` that
/// reverts also when the token returns `false`.
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) external {
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(
freeMemoryPointer,
0x23b872dd00000000000000000000000000000000000000000000000000000000
)
mstore(
add(freeMemoryPointer, 4),
and(from, 0xffffffffffffffffffffffffffffffffffffffff)
)
mstore(
add(freeMemoryPointer, 36),
and(to, 0xffffffffffffffffffffffffffffffffffffffff)
)
mstore(add(freeMemoryPointer, 68), value)
if iszero(call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
require(getLastTransferResult(token), "!transferFrom");
}
/// @dev Verifies that the last return was a successful `transfer*` call.
/// This is done by checking that the return data is either empty, or
/// is a valid ABI encoded boolean.
function getLastTransferResult(address token)
private
view
returns (bool success)
{
// NOTE: Inspecting previous return data requires assembly. Note that
// we write the return data to memory 0 in the case where the return
// data size is 32, this is OK since the first 64 bytes of memory are
// reserved by Solidy as a scratch space that can be used within
// assembly blocks.
// <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html>
// solhint-disable-next-line no-inline-assembly
assembly {
/// @dev Revert with an ABI encoded Solidity error with a message
/// that fits into 32-bytes.
///
/// An ABI encoded Solidity error has the following memory layout:
///
/// ------------+----------------------------------
/// byte range | value
/// ------------+----------------------------------
/// 0x00..0x04 | selector("Error(string)")
/// 0x04..0x24 | string offset (always 0x20)
/// 0x24..0x44 | string length
/// 0x44..0x64 | string value, padded to 32-bytes
function revertWithMessage(length, message) {
mstore(0x00, "\x08\xc3\x79\xa0")
mstore(0x04, 0x20)
mstore(0x24, length)
mstore(0x44, message)
revert(0x00, 0x64)
}
switch returndatasize()
// Non-standard ERC20 transfer without return.
case 0 {
// NOTE: When the return data size is 0, verify that there
// is code at the address. This is done in order to maintain
// compatibility with Solidity calling conventions.
// <https://docs.soliditylang.org/en/v0.7.6/control-structures.html#external-function-calls>
if iszero(extcodesize(token)) {
revertWithMessage(20, "!contract")
}
success := 1
}
// Standard ERC20 transfer returning boolean success value.
case 32 {
returndatacopy(0, 0, returndatasize())
// NOTE: For ABI encoding v1, any non-zero value is accepted
// as `true` for a boolean. In order to stay compatible with
// OpenZeppelin's `SafeERC20` library which is known to work
// with the existing ERC20 implementation we care about,
// make sure we return success for any non-zero return value
// from the `transfer*` call.
success := iszero(iszero(mload(0)))
}
default {
revertWithMessage(31, "malformed") // malformed transfer result
}
}
}
function safeTransferETH(address to, uint256 amount) external {
bool success;
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "!safeTransferETH");
}
}
VM.sol 123 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "./CommandBuilder.sol";
abstract contract VM {
using CommandBuilder for bytes[];
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 = 0x40;
uint256 constant FLAG_TUPLE_RETURN = 0x80;
uint256 constant SHORT_COMMAND_FILL = 0x000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
address immutable self;
error ExecutionFailed(
uint256 command_index,
address target,
string message
);
constructor() {
self = address(this);
}
function _execute(bytes32[] calldata commands, bytes[] memory state)
internal returns (bytes[] memory)
{
bytes32 command;
uint256 flags;
bytes32 indices;
bool success;
bytes memory outdata;
uint256 commandsLength = commands.length;
for (uint256 i; i < commandsLength;) {
command = commands[i];
flags = uint256(command >> 216) & 0xFF; // more efficient
// flags = uint256(uint8(bytes1(command << 32))); // more readable
if (flags & FLAG_EXTENDED_COMMAND != 0) {
indices = commands[++i];
} else {
indices = bytes32(uint256(command << 40) | SHORT_COMMAND_FILL);
}
if (flags & FLAG_CT_MASK == FLAG_CT_DELEGATECALL) {
(success, outdata) = address(uint160(uint256(command))).delegatecall( // target
// inputs
state.buildInputs(
//selector
bytes4(command),
indices
)
);
} else if (flags & FLAG_CT_MASK == FLAG_CT_CALL) {
(success, outdata) = address(uint160(uint256(command))).call( // target
// inputs
state.buildInputs(
//selector
bytes4(command),
indices
)
);
} else if (flags & FLAG_CT_MASK == FLAG_CT_STATICCALL) {
(success, outdata) = address(uint160(uint256(command))).staticcall( // target
// inputs
state.buildInputs(
//selector
bytes4(command),
indices
)
);
} else if (flags & FLAG_CT_MASK == FLAG_CT_VALUECALL) {
uint256 callEth;
bytes memory v = state[uint8(bytes1(indices))];
require(v.length == 32, "_execute: value call has no value indicated.");
assembly {
callEth := mload(add(v, 0x20))
}
(success, outdata) = address(uint160(uint256(command))).call{ // target
value: callEth
}(
// inputs
state.buildInputs(
//selector
bytes4(command),
bytes32(uint256(indices << 8) | CommandBuilder.IDX_END_OF_ARGS)
)
);
} else {
revert("Invalid calltype");
}
if (!success) {
if (outdata.length > 0) {
assembly {
outdata := add(outdata, 68)
}
}
revert ExecutionFailed({
command_index: 0,
target: address(uint160(uint256(command))),
message: outdata.length > 0 ? string(outdata) : "Unknown"
});
}
if (flags & FLAG_TUPLE_RETURN != 0) {
state.writeTuple(bytes1(command << 88), outdata);
} else {
state = state.writeOutputs(bytes1(command << 88), outdata);
}
unchecked{++i;}
}
return state;
}
}
Read Contract
governance 0x5aa6e675 → address
mechs 0x49d6e212 → bool
pendingGovernance 0xf39c38a0 → address
settlement 0x51160630 → address
solvers 0x57f58d98 → bool
treasury 0x61d027b3 → address
Write Contract 13 functions
These functions modify contract state and require a wallet transaction to execute.
acceptGovernance 0x238efcbc
No parameters
addMech 0xd0adcdf6
address _mech
addSolver 0xec58f4b8
address _solver
disable 0x9cd38be5
address _tokenIn
address _tokenOut
disableByAdmin 0x00b8ff92
address _strategy
address _tokenIn
address _tokenOut
enable 0x4c854126
address _tokenIn
address _tokenOut
execute 0xde792d5f
bytes32[] commands
bytes[] state
returns: bytes[]
removeMech 0x66f88f82
address _mech
removeSolver 0x8fd57b92
address _solver
setGovernance 0xab033ea9
address _governance
setSettlement 0x8f4e6f37
address _settlement
setTreasury 0xf0f44260
address _treasury
sweep 0x9ed6c6f6
address[] _tokens
uint256[] _amounts
Token Balances (8)
View Transfers →Recent Transactions
No transactions found for this address