Solidity
幫我理解這個智能合約的流程
我有 2 個智能合約,下面是它們的實現:
1) import "./MaintainableUpgradeabilityProxy.sol"; function _createProxy(address implementation, address serviceRegistry) internal returns (MaintainableUpgradeabilityProxy) { MaintainableUpgradeabilityProxy proxy = new MaintainableUpgradeabilityProxy(implementation, serviceRegistry); emit ProxyCreated(proxy, msg.sender); return proxy; }
可維護升級能力代理.sol –>
2) pragma solidity ^0.4.22; import "zos-lib/contracts/upgradeability/UpgradeabilityProxy.sol"; import "../registry/interface/IServiceRegistry.sol"; /** * @title AdminUpgradeabilityProxy * @dev This contract combines an upgradeability proxy with an authorization * mechanism for administrative tasks. * All external functions in this contract must be guarded by the * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity * feature proposal that would enable this to be done automatically. */ contract MaintainableUpgradeabilityProxy is UpgradeabilityProxy { /** * @dev Emitted when the administration has been transferred. * @param previousRegistry Address of the previous registry. * @param newRegistry Address of the new registry. */ event ServiceRegistryChanged(address previousRegistry, address newRegistry); /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is * validated in the constructor. */ bytes32 private constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b; /** * @dev Modifier to check whether the `msg.sender` is the admin. * If it is, it will run the function. Otherwise, it will delegate the call * to the implementation. */ modifier ifMaintainer() { if (IServiceRegistry(_serviceRegistry()).getMaintainerRegistryV1().isMaintainer(msg.sender)) { _; } else { _fallback(); } } /** * Contract constructor. * It sets the `msg.sender` as the proxy administrator. * @param _implementation address of the initial implementation. */ constructor(address _implementation, address _serviceReg) UpgradeabilityProxy(_implementation) public { assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin")); _setServiceRegistry(_serviceReg); } /** * @return The address of the implementation. */ function implementation() external view ifMaintainer returns (address) { return _implementation(); } /** * @dev Changes the service registry of the proxy. * Only the current admin can call this function. * @param _newRegistry Address to transfer proxy administration to. */ function changeServiceRegistry(address _newRegistry) external ifMaintainer { require(_newRegistry != address(0), "New registry cannot be address(0)"); emit ServiceRegistryChanged(_serviceRegistry(), _newRegistry); _setServiceRegistry(_newRegistry); } /** * @dev Upgrade the backing implementation of the proxy. * Only the maintainers can call this function. * @param newImplementation Address of the new implementation. */ function upgradeTo(address newImplementation) external ifMaintainer { _upgradeTo(newImplementation); } /** * @dev Upgrade the backing implementation of the proxy and call a function * on the new implementation. * This is useful to initialize the proxied contract. * @param _implementation Address of the new implementation. * @param data Data to send as msg.data in the low level call. * It should include the signature and the parameters of the function to be * called, as described in * https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding. */ function upgradeToAndCall(address _implementation, bytes data) external payable ifMaintainer { _upgradeTo(_implementation); // solium-disable-next-line security/no-call-value require(address(this).call.value(msg.value)(data), "Call failed"); } /** * @return The service registry slot. */ function _serviceRegistry() internal view returns (address _serviceReg) { bytes32 slot = ADMIN_SLOT; // solium-disable-next-line security/no-inline-assembly assembly { _serviceReg := sload(slot) } } /** * @dev Sets the address of the proxy admin. * @param _serviceReg Address to use */ function _setServiceRegistry(address _serviceReg) internal { bytes32 slot = ADMIN_SLOT; // solium-disable-next-line security/no-inline-assembly assembly { sstore(slot, _serviceReg) } } /** * @dev Only fall back when the sender is not a maintainer. */ function _willFallback() internal { require( !IServiceRegistry(_serviceRegistry()).getMaintainerRegistryV1().isMaintainer(msg.sender), "Maintainer cannot call fallback functions"); super._willFallback(); } }
事情從我
_createProxy(address1, address2)
從契約 1開始我感到困惑的是:
- 合約 1 的函式 _createProxy 的返回類型
function _createProxy(address implementation, address serviceRegistry) public returns (MaintainableUpgradeabilityProxy) {...}
這
MaintainableUpgradeabilityProxy
是合約的名稱,那麼它返回的合約地址是什麼?2)MaintainableUpgradeabilityProxy的函式_createProxy內部新實例在
MaintainableUpgradeabilityProxy `proxy` = new MaintainableUpgradeabilityProxy(implementation, serviceRegistry);
它應該呼叫它的建構子,該建構子正在呼叫 _setServiceRegistry,它什麼都不返回,那麼變數代理將接收什麼值?
- _setServiceRegistry() 中發生了什麼
這裡 MaintainableUpgradeabilityProxy 是合約的名稱,那麼它返回的合約地址是什麼?
是的。這樣做和返回地址的區別在於,如果另一個合約呼叫了這個方法,那麼它將接收到那個合約實例。相當於返回了合約的地址,然後
MaintainableUpgradeabilityProxy(returnedAddress)
在呼叫者裡面做。例如,如果您有:
contract Foo { function returnContract() returns (SomeContract) { SomeContract sc = new SomeContract(); return sc; } function returnAddress() returns (address) { SomeContract sc = new SomeContract(); return address(sc); } }
那麼
foo.returnContract()
幾乎等同於SomeContract(foo.returnAddress())
我認為goodvibration的評論回答了其餘的問題。