Transactions
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Read Proxy
Write Contract
Write Proxy
- Contract name:
- WitnetProxy
- Optimization enabled
- true
- Compiler version
- v0.8.13+commit.abaa5c0e
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2022-04-18 10:40:41.502716Z
Contract source code
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
pragma experimental ABIEncoderV2;
// File: contracts\patterns\Initializable.sol
interface Initializable {
/// @dev Initialize contract's storage context.
function initialize(bytes calldata) external;
}
// File: contracts\patterns\Proxiable.sol
interface Proxiable {
/// @dev Complying with EIP-1822: Universal Upgradable Proxy Standard (UUPS)
/// @dev See https://eips.ethereum.org/EIPS/eip-1822.
function proxiableUUID() external pure returns (bytes32);
}
// File: contracts\patterns\Upgradable.sol
/* solhint-disable var-name-mixedcase */
abstract contract Upgradable is Initializable, Proxiable {
address internal immutable _BASE;
bytes32 internal immutable _CODEHASH;
bool internal immutable _UPGRADABLE;
/// Emitted every time the contract gets upgraded.
/// @param from The address who ordered the upgrading. Namely, the WRB operator in "trustable" implementations.
/// @param baseAddr The address of the new implementation contract.
/// @param baseCodehash The EVM-codehash of the new implementation contract.
/// @param versionTag Ascii-encoded version literal with which the implementation deployer decided to tag it.
event Upgraded(
address indexed from,
address indexed baseAddr,
bytes32 indexed baseCodehash,
bytes32 versionTag
);
constructor (bool _isUpgradable) {
address _base = address(this);
bytes32 _codehash;
assembly {
_codehash := extcodehash(_base)
}
_BASE = _base;
_CODEHASH = _codehash;
_UPGRADABLE = _isUpgradable;
}
/// @dev Tells whether provided address could eventually upgrade the contract.
function isUpgradableFrom(address from) virtual external view returns (bool);
/// TODO: the following methods should be all declared as pure
/// whenever this Solidity's PR gets merged and released:
/// https://github.com/ethereum/solidity/pull/10240
/// @dev Retrieves base contract. Differs from address(this) when via delegate-proxy pattern.
function base() public view returns (address) {
return _BASE;
}
/// @dev Retrieves the immutable codehash of this contract, even if invoked as delegatecall.
/// @return _codehash This contracts immutable codehash.
function codehash() public view returns (bytes32 _codehash) {
return _CODEHASH;
}
/// @dev Determines whether current instance allows being upgraded.
/// @dev Returned value should be invariant from whoever is calling.
function isUpgradable() public view returns (bool) {
return _UPGRADABLE;
}
/// @dev Retrieves human-redable named version of current implementation.
function version() virtual public view returns (bytes32);
}
// File: contracts\impls\WitnetProxy.sol
/// @title WitnetProxy: upgradable delegate-proxy contract that routes Witnet data requests coming from a
/// `UsingWitnet`-inheriting contract to a currently active `WitnetRequestBoard` implementation.
/// @author The Witnet Foundation.
contract WitnetProxy {
struct WitnetProxySlot {
address implementation;
}
/// Event emitted every time the implementation gets updated.
event Upgraded(address indexed implementation);
/// Constructor with no params as to ease eventual support of Singleton pattern (i.e. ERC-2470).
constructor () {}
/// WitnetProxies will never accept direct transfer of ETHs.
receive() external payable {
revert("WitnetProxy: no transfers accepted");
}
/// Payable fallback accepts delegating calls to payable functions.
fallback() external payable { /* solhint-disable no-complex-fallback */
address _implementation = implementation();
assembly { /* solhint-disable avoid-low-level-calls */
// Gas optimized delegate call to 'implementation' contract.
// Note: `msg.data`, `msg.sender` and `msg.value` will be passed over
// to actual implementation of `msg.sig` within `implementation` contract.
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize())
let result := delegatecall(gas(), _implementation, ptr, calldatasize(), 0, 0)
let size := returndatasize()
returndatacopy(ptr, 0, size)
switch result
case 0 {
// pass back revert message:
revert(ptr, size)
}
default {
// pass back same data as returned by 'implementation' contract:
return(ptr, size)
}
}
}
/// Returns proxy's current implementation address.
function implementation() public view returns (address) {
return _proxySlot().implementation;
}
/// Upgrades the `implementation` address.
/// @param _newImplementation New implementation address.
/// @param _initData Raw data with which new implementation will be initialized.
/// @return Returns whether new implementation would be further upgradable, or not.
function upgradeTo(address _newImplementation, bytes memory _initData)
public returns (bool)
{
// New implementation cannot be null:
require(_newImplementation != address(0), "WitnetProxy: null implementation");
address _oldImplementation = implementation();
if (_oldImplementation != address(0)) {
// New implementation address must differ from current one:
require(_newImplementation != _oldImplementation, "WitnetProxy: nothing to upgrade");
// Assert whether current implementation is intrinsically upgradable:
try Upgradable(_oldImplementation).isUpgradable() returns (bool _isUpgradable) {
require(_isUpgradable, "WitnetProxy: not upgradable");
} catch {
revert("WitnetProxy: unable to check upgradability");
}
// Assert whether current implementation allows `msg.sender` to upgrade the proxy:
(bool _wasCalled, bytes memory _result) = _oldImplementation.delegatecall(
abi.encodeWithSignature(
"isUpgradableFrom(address)",
msg.sender
)
);
require(_wasCalled, "WitnetProxy: not compliant");
require(abi.decode(_result, (bool)), "WitnetProxy: not authorized");
require(
Upgradable(_oldImplementation).proxiableUUID() == Upgradable(_newImplementation).proxiableUUID(),
"WitnetProxy: proxiableUUIDs mismatch"
);
}
// Initialize new implementation within proxy-context storage:
(bool _wasInitialized,) = _newImplementation.delegatecall(
abi.encodeWithSignature(
"initialize(bytes)",
_initData
)
);
require(_wasInitialized, "WitnetProxy: unable to initialize");
// If all checks and initialization pass, update implementation address:
_proxySlot().implementation = _newImplementation;
emit Upgraded(_newImplementation);
// Asserts new implementation complies w/ minimal implementation of Upgradable interface:
try Upgradable(_newImplementation).isUpgradable() returns (bool _isUpgradable) {
return _isUpgradable;
}
catch {
revert ("WitnetProxy: not compliant");
}
}
/// @dev Complying with EIP-1967, retrieves storage struct containing proxy's current implementation address.
function _proxySlot() private pure returns (WitnetProxySlot storage _slot) {
assembly {
// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
_slot.slot := 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
}
}
}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"implementation","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"upgradeTo","inputs":[{"type":"address","name":"_newImplementation","internalType":"address"},{"type":"bytes","name":"_initData","internalType":"bytes"}]},{"type":"receive","stateMutability":"payable"}]
Deployed ByteCode
0x60806040526004361061002d5760003560e01c80635c60da1b146100bb5780636fbc15e9146100ed5761008a565b3661008a5760405162461bcd60e51b815260206004820152602260248201527f5769746e657450726f78793a206e6f207472616e736665727320616363657074604482015261195960f21b60648201526084015b60405180910390fd5b600061009461011d565b905060405136600082376000803683855af43d806000843e8180156100b7578184f35b8184fd5b3480156100c757600080fd5b506100d061011d565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100f957600080fd5b5061010d6101083660046107a8565b61014b565b60405190151581526020016100e4565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b60006001600160a01b0383166101a35760405162461bcd60e51b815260206004820181905260248201527f5769746e657450726f78793a206e756c6c20696d706c656d656e746174696f6e6044820152606401610081565b60006101ad61011d565b90506001600160a01b0381161561058957806001600160a01b0316846001600160a01b03160361021f5760405162461bcd60e51b815260206004820152601f60248201527f5769746e657450726f78793a206e6f7468696e6720746f2075706772616465006044820152606401610081565b806001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610279575060408051601f3d908101601f1916820190925261027691810190610878565b60015b6102d85760405162461bcd60e51b815260206004820152602a60248201527f5769746e657450726f78793a20756e61626c6520746f20636865636b207570676044820152697261646162696c69747960b01b6064820152608401610081565b806103255760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f742075706772616461626c6500000000006044820152606401610081565b5060405133602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166335ac4b0560e11b1790525161037791906108d1565b600060405180830381855af49150503d80600081146103b2576040519150601f19603f3d011682016040523d82523d6000602084013e6103b7565b606091505b5091509150816104095760405162461bcd60e51b815260206004820152601a60248201527f5769746e657450726f78793a206e6f7420636f6d706c69616e740000000000006044820152606401610081565b8080602001905181019061041d9190610878565b6104695760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f7420617574686f72697a656400000000006044820152606401610081565b856001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cb91906108ed565b836001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610509573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052d91906108ed565b146105865760405162461bcd60e51b8152602060048201526024808201527f5769746e657450726f78793a2070726f786961626c655555494473206d69736d6044820152630c2e8c6d60e31b6064820152608401610081565b50505b6000846001600160a01b0316846040516024016105a69190610906565b60408051601f198184030181529181526020820180516001600160e01b031663439fab9160e01b179052516105db91906108d1565b600060405180830381855af49150503d8060008114610616576040519150601f19603f3d011682016040523d82523d6000602084013e61061b565b606091505b50509050806106765760405162461bcd60e51b815260206004820152602160248201527f5769746e657450726f78793a20756e61626c6520746f20696e697469616c697a6044820152606560f81b6064820152608401610081565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0387169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2846001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610736575060408051601f3d908101601f1916820190925261073391810190610878565b60015b6107825760405162461bcd60e51b815260206004820152601a60248201527f5769746e657450726f78793a206e6f7420636f6d706c69616e740000000000006044820152606401610081565b925061078c915050565b92915050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156107bb57600080fd5b82356001600160a01b03811681146107d257600080fd5b9150602083013567ffffffffffffffff808211156107ef57600080fd5b818501915085601f83011261080357600080fd5b81358181111561081557610815610792565b604051601f8201601f19908116603f0116810190838211818310171561083d5761083d610792565b8160405282815288602084870101111561085657600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60006020828403121561088a57600080fd5b8151801515811461089a57600080fd5b9392505050565b60005b838110156108bc5781810151838201526020016108a4565b838111156108cb576000848401525b50505050565b600082516108e38184602087016108a1565b9190910192915050565b6000602082840312156108ff57600080fd5b5051919050565b60208152600082518060208401526109258160408501602087016108a1565b601f01601f1916919091016040019291505056fea2646970667358221220b619e4409b993dc8e9a7402d8633b5aa1ac562d85786959d0b4e04e75a98020164736f6c634300080d0033