// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import { IProxy } from'../interfaces/IProxy.sol';
/**
* @title BaseProxy Contract
* @dev This abstract contract implements a basic proxy that stores an implementation address. Fallback function
* calls are delegated to the implementation. This contract is meant to be inherited by other proxy contracts.
*/abstractcontractBaseProxyisIProxy{
// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)bytes32internalconstant _IMPLEMENTATION_SLOT =0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
// keccak256('owner')bytes32internalconstant _OWNER_SLOT =0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;
/**
* @dev Returns the current implementation address.
* @return implementation_ The address of the current implementation contract
*/functionimplementation() publicviewvirtualreturns (address implementation_) {
assembly {
implementation_ :=sload(_IMPLEMENTATION_SLOT)
}
}
/**
* @dev Shadows the setup function of the implementation contract so it can't be called directly via the proxy.
* @param params The setup parameters for the implementation contract.
*/functionsetup(bytescalldata params) external{}
/**
* @dev Returns the contract ID. It can be used as a check during upgrades. Meant to be implemented in derived contracts.
* @return bytes32 The contract ID
*/functioncontractId() internalpurevirtualreturns (bytes32);
/**
* @dev Fallback function. Delegates the call to the current implementation contract.
*/fallback() externalpayablevirtual{
address implementation_ = implementation();
assembly {
calldatacopy(0, 0, calldatasize())
let result :=delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @dev Payable fallback function. Can be overridden in derived contracts.
*/receive() externalpayablevirtual{}
}
Contract Source Code
File 2 of 5: IContractIdentifier.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;// General interface for upgradable contractsinterfaceIContractIdentifier{
/**
* @notice Returns the contract ID. It can be used as a check during upgrades.
* @dev Meant to be overridden in derived contracts.
* @return bytes32 The contract ID
*/functioncontractId() externalpurereturns (bytes32);
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import { Proxy } from'@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradable/Proxy.sol';
/**
* @title InterchainProxy
* @notice This contract is a proxy for interchainTokenService and interchainTokenFactory.
* @dev This contract implements Proxy.
*/contractInterchainProxyisProxy{
constructor(address implementationAddress, address owner, bytesmemory setupParams) Proxy(implementationAddress, owner, setupParams) {}
}
Contract Source Code
File 5 of 5: Proxy.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import { IProxy } from'../interfaces/IProxy.sol';
import { IContractIdentifier } from'../interfaces/IContractIdentifier.sol';
import { BaseProxy } from'./BaseProxy.sol';
/**
* @title Proxy Contract
* @notice A proxy contract that delegates calls to a designated implementation contract. Inherits from BaseProxy.
* @dev The constructor takes in the address of the implementation contract, the owner address, and any optional setup
* parameters for the implementation contract.
*/contractProxyisBaseProxy{
/**
* @notice Constructs the proxy contract with the implementation address, owner address, and optional setup parameters.
* @param implementationAddress The address of the implementation contract
* @param owner The owner address
* @param setupParams Optional parameters to setup the implementation contract
* @dev The constructor verifies that the owner address is not the zero address and that the contract ID of the implementation is valid.
* It then stores the implementation address and owner address in their designated storage slots and calls the setup function on the
* implementation (if setup params exist).
*/constructor(address implementationAddress,
address owner,
bytesmemory setupParams
) {
if (owner ==address(0)) revert InvalidOwner();
bytes32 id = contractId();
// Skipping the check if contractId() is not set by an inheriting proxy contractif (id !=bytes32(0) && IContractIdentifier(implementationAddress).contractId() != id)
revert InvalidImplementation();
assembly {
sstore(_IMPLEMENTATION_SLOT, implementationAddress)
sstore(_OWNER_SLOT, owner)
}
if (setupParams.length!=0) {
(bool success, ) = implementationAddress.delegatecall(
abi.encodeWithSelector(BaseProxy.setup.selector, setupParams)
);
if (!success) revert SetupFailed();
}
}
functioncontractId() internalpurevirtualoverridereturns (bytes32) {
returnbytes32(0);
}
}