文件 1 的 3:AxelarGasServiceProxy.sol
pragma solidity 0.8.9;
import { Proxy } from '../util/Proxy.sol';
import { IUpgradable } from '../interfaces/IUpgradable.sol';
contract AxelarGasServiceProxy is Proxy {
function contractId() internal pure override returns (bytes32) {
return keccak256('axelar-gas-service');
}
}
文件 2 的 3:IUpgradable.sol
pragma solidity ^0.8.9;
interface IUpgradable {
error NotOwner();
error InvalidOwner();
error InvalidCodeHash();
error InvalidImplementation();
error SetupFailed();
error NotProxy();
event Upgraded(address indexed newImplementation);
event OwnershipTransferred(address indexed newOwner);
function owner() external view returns (address);
function contractId() external pure returns (bytes32);
function implementation() external view returns (address);
function upgrade(
address newImplementation,
bytes32 newImplementationCodeHash,
bytes calldata params
) external;
function setup(bytes calldata data) external;
}
文件 3 的 3:Proxy.sol
pragma solidity 0.8.9;
import { IUpgradable } from '../interfaces/IUpgradable.sol';
contract Proxy {
error InvalidImplementation();
error SetupFailed();
error EtherNotAccepted();
error NotOwner();
error AlreadyInitialized();
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;
constructor() {
assembly {
sstore(_OWNER_SLOT, caller())
}
}
function init(
address implementationAddress,
address newOwner,
bytes memory params
) external {
address owner;
assembly {
owner := sload(_OWNER_SLOT)
}
if (msg.sender != owner) revert NotOwner();
if (implementation() != address(0)) revert AlreadyInitialized();
if (IUpgradable(implementationAddress).contractId() != contractId()) revert InvalidImplementation();
assembly {
sstore(_IMPLEMENTATION_SLOT, implementationAddress)
sstore(_OWNER_SLOT, newOwner)
}
(bool success, ) = implementationAddress.delegatecall(
abi.encodeWithSelector(0x9ded06df, params)
);
if (!success) revert SetupFailed();
}
function contractId() internal pure virtual returns (bytes32) {}
function implementation() public view returns (address implementation_) {
assembly {
implementation_ := sload(_IMPLEMENTATION_SLOT)
}
}
function setup(bytes calldata data) public {}
fallback() external payable {
address implementaion_ = implementation();
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementaion_, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
receive() external payable virtual {
revert EtherNotAccepted();
}
}
{
"compilationTarget": {
"contracts/gas-service/AxelarGasServiceProxy.sol": "AxelarGasServiceProxy"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"EtherNotAccepted","type":"error"},{"inputs":[],"name":"InvalidImplementation","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"SetupFailed","type":"error"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"implementationAddress","type":"address"},{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]