Skip to content

Instantly share code, notes, and snippets.

@wschwab
Last active October 31, 2022 17:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wschwab/e5794a8c3a25a98dcd8dfd54a69c4baa to your computer and use it in GitHub Desktop.
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
// 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