Transaction Hash:
Block:
12455783 at May-18-2021 02:47:18 AM +UTC
Transaction Fee:
0.029202824 ETH
$62.77
Gas Used:
595,976 Gas / 49 Gwei
Emitted Events:
| 73 |
0x90b32db0fac877e57849501bfd7f6bc5b5884c07.0xce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed94( 0xce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed94, 0x000000000000000000000000a26e15c895efc0616177b7c1e7270a4c7d51c997 )
|
| 74 |
0x90b32db0fac877e57849501bfd7f6bc5b5884c07.0x0000000000000000000000000000000000000000000000000000000000000000( 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a26e15c895efc0616177b7c1e7270a4c7d51c997, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 75 |
DSProxyFactory.Created( sender=[Receiver] ProxyRegistry, owner=[Sender] 0xeefc2c3f7ceced2f2ec7e355c09d69ad4264cd90, proxy=0x90b32db0fac877e57849501bfd7f6bc5b5884c07, cache=0x271293c6...1E07B0795 )
|
| 76 |
0x90b32db0fac877e57849501bfd7f6bc5b5884c07.0xce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed94( 0xce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed94, 0x000000000000000000000000eefc2c3f7ceced2f2ec7e355c09d69ad4264cd90 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
|
0x00192Fb1...d1BF599E8
Miner
| (2Miners: PPLNS) | 1,419.784600334207383477 Eth | 1,419.813803158207383477 Eth | 0.029202824 | |
| 0x4678f0a6...3564f3fE4 | (Sky: Proxy Registry) | ||||
| 0x90B32dB0...5b5884c07 | (DSProxy #202,612) |
0 Eth
Nonce: 0
|
0 Eth
Nonce: 1
| ||
| 0xA26e15C8...C7D51C997 | (Sky: DS Proxy Factory) | ||||
| 0xEEFC2c3f...d4264cD90 |
8 Eth
Nonce: 0
|
7.970797176 Eth
Nonce: 1
| 0.029202824 |
Execution Trace
ProxyRegistry.CALL( )
DSProxyFactory.build( owner=0xEEFC2c3f7cecEd2f2ec7e355c09d69Ad4264cD90 ) => ( proxy=0x90B32dB0FaC877E57849501Bfd7f6BC5b5884c07 )-
DSProxy #202,612.60806040( ) -
DSProxy #202,612.13af4035( )
-
File 1 of 2: ProxyRegistry
File 2 of 2: DSProxyFactory
// proxy.sol - execute actions atomically through the proxy's identity
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.4.23;
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() public {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
emit LogSetAuthority(authority);
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, this, sig);
}
}
}
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
// DSProxy
// Allows code execution using a persistant identity This can be very
// useful to execute a sequence of atomic actions. Since the owner of
// the proxy can be changed, this allows for dynamic ownership models
// i.e. a multisig
contract DSProxy is DSAuth, DSNote {
DSProxyCache public cache; // global cache for contracts
constructor(address _cacheAddr) public {
require(setCache(_cacheAddr));
}
function() public payable {
}
// use the proxy to execute calldata _data on contract _code
function execute(bytes _code, bytes _data)
public
payable
returns (address target, bytes32 response)
{
target = cache.read(_code);
if (target == 0x0) {
// deploy contract & store its address in cache
target = cache.write(_code);
}
response = execute(target, _data);
}
function execute(address _target, bytes _data)
public
auth
note
payable
returns (bytes32 response)
{
require(_target != 0x0);
// call contract in current context
assembly {
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 32)
response := mload(0) // load delegatecall output
switch iszero(succeeded)
case 1 {
// throw if delegatecall failed
revert(0, 0)
}
}
}
//set new cache
function setCache(address _cacheAddr)
public
auth
note
returns (bool)
{
require(_cacheAddr != 0x0); // invalid cache address
cache = DSProxyCache(_cacheAddr); // overwrite cache
return true;
}
}
// DSProxyFactory
// This factory deploys new proxy instances through build()
// Deployed proxy addresses are logged
contract DSProxyFactory {
event Created(address indexed sender, address indexed owner, address proxy, address cache);
mapping(address=>bool) public isProxy;
DSProxyCache public cache = new DSProxyCache();
// deploys a new proxy instance
// sets owner of proxy to caller
function build() public returns (DSProxy proxy) {
proxy = build(msg.sender);
}
// deploys a new proxy instance
// sets custom owner of proxy
function build(address owner) public returns (DSProxy proxy) {
proxy = new DSProxy(cache);
emit Created(msg.sender, owner, address(proxy), address(cache));
proxy.setOwner(owner);
isProxy[proxy] = true;
}
}
// DSProxyCache
// This global cache stores addresses of contracts previously deployed
// by a proxy. This saves gas from repeat deployment of the same
// contracts and eliminates blockchain bloat.
// By default, all proxies deployed from the same factory store
// contracts in the same cache. The cache a proxy instance uses can be
// changed. The cache uses the sha3 hash of a contract's bytecode to
// lookup the address
contract DSProxyCache {
mapping(bytes32 => address) cache;
function read(bytes _code) public view returns (address) {
bytes32 hash = keccak256(_code);
return cache[hash];
}
function write(bytes _code) public returns (address target) {
assembly {
target := create(0, add(_code, 0x20), mload(_code))
switch iszero(extcodesize(target))
case 1 {
// throw if contract failed to deploy
revert(0, 0)
}
}
bytes32 hash = keccak256(_code);
cache[hash] = target;
}
}
// ProxyRegistry
// This Registry deploys new proxy instances through DSProxyFactory.build(address) and keeps a registry of owner => proxy
contract ProxyRegistry {
mapping(address => DSProxy) public proxies;
DSProxyFactory factory;
constructor(DSProxyFactory factory_) public {
factory = factory_;
}
// deploys a new proxy instance
// sets owner of proxy to caller
function build() public returns (DSProxy proxy) {
proxy = build(msg.sender);
}
// deploys a new proxy instance
// sets custom owner of proxy
function build(address owner) public returns (DSProxy proxy) {
require(proxies[owner] == DSProxy(0) || proxies[owner].owner() != owner); // Not allow new proxy if the user already has one and remains being the owner
proxy = factory.build(owner);
proxies[owner] = proxy;
}
}File 2 of 2: DSProxyFactory
// proxy.sol - execute actions atomically through the proxy's identity
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.4.23;
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() public {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
emit LogSetAuthority(authority);
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, this, sig);
}
}
}
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
// DSProxy
// Allows code execution using a persistant identity This can be very
// useful to execute a sequence of atomic actions. Since the owner of
// the proxy can be changed, this allows for dynamic ownership models
// i.e. a multisig
contract DSProxy is DSAuth, DSNote {
DSProxyCache public cache; // global cache for contracts
constructor(address _cacheAddr) public {
require(setCache(_cacheAddr));
}
function() public payable {
}
// use the proxy to execute calldata _data on contract _code
function execute(bytes _code, bytes _data)
public
payable
returns (address target, bytes32 response)
{
target = cache.read(_code);
if (target == 0x0) {
// deploy contract & store its address in cache
target = cache.write(_code);
}
response = execute(target, _data);
}
function execute(address _target, bytes _data)
public
auth
note
payable
returns (bytes32 response)
{
require(_target != 0x0);
// call contract in current context
assembly {
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 32)
response := mload(0) // load delegatecall output
switch iszero(succeeded)
case 1 {
// throw if delegatecall failed
revert(0, 0)
}
}
}
//set new cache
function setCache(address _cacheAddr)
public
auth
note
returns (bool)
{
require(_cacheAddr != 0x0); // invalid cache address
cache = DSProxyCache(_cacheAddr); // overwrite cache
return true;
}
}
// DSProxyFactory
// This factory deploys new proxy instances through build()
// Deployed proxy addresses are logged
contract DSProxyFactory {
event Created(address indexed sender, address indexed owner, address proxy, address cache);
mapping(address=>bool) public isProxy;
DSProxyCache public cache = new DSProxyCache();
// deploys a new proxy instance
// sets owner of proxy to caller
function build() public returns (DSProxy proxy) {
proxy = build(msg.sender);
}
// deploys a new proxy instance
// sets custom owner of proxy
function build(address owner) public returns (DSProxy proxy) {
proxy = new DSProxy(cache);
emit Created(msg.sender, owner, address(proxy), address(cache));
proxy.setOwner(owner);
isProxy[proxy] = true;
}
}
// DSProxyCache
// This global cache stores addresses of contracts previously deployed
// by a proxy. This saves gas from repeat deployment of the same
// contracts and eliminates blockchain bloat.
// By default, all proxies deployed from the same factory store
// contracts in the same cache. The cache a proxy instance uses can be
// changed. The cache uses the sha3 hash of a contract's bytecode to
// lookup the address
contract DSProxyCache {
mapping(bytes32 => address) cache;
function read(bytes _code) public view returns (address) {
bytes32 hash = keccak256(_code);
return cache[hash];
}
function write(bytes _code) public returns (address target) {
assembly {
target := create(0, add(_code, 0x20), mload(_code))
switch iszero(extcodesize(target))
case 1 {
// throw if contract failed to deploy
revert(0, 0)
}
}
bytes32 hash = keccak256(_code);
cache[hash] = target;
}
}