Last active
October 31, 2022 17:25
-
-
Save wschwab/e5794a8c3a25a98dcd8dfd54a69c4baa to your computer and use it in GitHub Desktop.
Rough reconstruciton of the source code for the contract at 0xa57Bd00134B2850B2a1c55860c9e9ea100fDd6CF on eth mainnet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity 0.8.15; | |
// current thinking is that the original was compiled on 0.5.0 or 0.5.1 | |
// after seeing significant code reuse from DSProxy, assumptions have been made | |
// the presence of cache() and setCache() imply usage of DSProxyCache | |
interface DSProxyCache { | |
function read(bytes memory _code) external view returns (address); | |
function write(bytes memory _code) external returns (address); | |
} | |
/// @title 0xa57 | |
/// @dev a rough approximation of the contract at 0xa57Bd00134B2850B2a1c55860c9e9ea100fDd6CF on Ethereum mainnet | |
/// @notice still a work in progress, full of guesses | |
contract ZeroXa57 { | |
mapping(address => uint) public wards; | |
function rely(address usr) external { | |
require(wards[msg.sender] == 1); | |
wards[usr] = 1; | |
} | |
function deny(address usr) external { | |
require(wards[msg.sender] == 1); | |
wards[usr] = 0; | |
} | |
DSProxyCache public cache; | |
constructor(address _cacheAddr) { | |
setCache(_cacheAddr); | |
} | |
fallback() external payable {} | |
// not sure this version returns anything, keeping ds-proxy's return values | |
function execute(bytes memory _code, bytes memory _data) | |
public | |
payable | |
returns (address target, bytes memory response) | |
{ | |
target = cache.read(_code); | |
if (target == address(0)) { | |
// deploy contract & store its address in cache | |
target = cache.write(_code); | |
} | |
response = execute(target, _data); | |
} | |
// this version of execute follows an old version of the function in | |
// ds-proxy which does not return error msgs from failed delegatecalls | |
// for example: | |
// https://github.com/dapphub/ds-proxy/blob/9ccaf3d04d960a20ffbcb57041e0867d9e55b4f9/src/proxy.sol#L54-L79 | |
// not sure this version returns anything, keeping ds-proxy's return values | |
function execute(address _target, bytes memory _data) | |
public | |
payable | |
returns (bytes memory response) | |
{ | |
require(wards[msg.sender] == 1); | |
require(_target != 0x0); | |
// call contract in current context | |
assembly { | |
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0) | |
let size := returndatasize | |
response := mload(0x40) | |
mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) | |
mstore(response, size) | |
returndatacopy(add(response, 0x20), 0, size) | |
switch iszero(succeeded) | |
case 1 { | |
// throw if delegatecall failed | |
revert(0, 0) | |
} | |
} | |
} | |
// unknown function name, is otherwise identical to execute(bytes,bytes) | |
// except that it seems to call 0x78e111f6 instead of execute(address,bytes) | |
// not sure this version returns anything, keeping ds-proxy's return values | |
function 0xa90e8731(bytes memory _code, bytes memory _data) | |
public | |
payable | |
returns (address target, bytes memory response) | |
{ | |
target = cache.read(_code); | |
if (target == address(0)) { | |
// deploy contract & store its address in cache | |
target = cache.write(_code); | |
} | |
response = 0x78e111f6(target, _data); | |
} | |
// unknown function name, is otherwise identical to execute(address,bytes) | |
// except that this one returns error msgs from a failed delegatecall | |
// whereas the execute(address,bytes) used here does not | |
// the code here is taken from later versions of ds-proxy, where execute | |
// does return an error message | |
// not sure this version returns anything, keeping ds-proxy's return values | |
function 0x78e111f6(address _target, bytes memory _data) | |
public | |
payable | |
returns (bytes memory response) | |
{ | |
require(wards[msg.sender] == 1); | |
require(_target != address(0), "ds-proxy-target-address-required"); | |
// call contract in current context | |
assembly { | |
let succeeded := delegatecall( | |
sub(gas(), 5000), | |
_target, | |
add(_data, 0x20), | |
mload(_data), | |
0, | |
0 | |
) | |
let size := returndatasize() | |
response := mload(0x40) | |
mstore( | |
0x40, | |
add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))) | |
) | |
mstore(response, size) | |
returndatacopy(add(response, 0x20), 0, size) | |
switch iszero(succeeded) | |
case 1 { | |
// throw if delegatecall failed | |
revert(add(response, 0x20), size) | |
} | |
} | |
} | |
function setCache(address _cacheAddr) public payable returns (bool) { | |
require(wards[msg.sender] == 1); | |
require(_cacheAddr != address(0), "ds-proxy-cache-address-required"); | |
cache = DSProxyCache(_cacheAddr); // overwrite cache | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment