diff options
author | Chris Ward <chris.ward@ethereum.org> | 2019-01-07 18:04:31 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2019-01-08 00:48:24 +0800 |
commit | 26d47c7213ac8bb26fabd8d761567d940c55cfe3 (patch) | |
tree | ef229a700daec864103a4af074ef0cb70ae78166 | |
parent | 40e1283d728b0f456bb8d23b73c7c3953004edfb (diff) | |
download | dexon-solidity-26d47c7213ac8bb26fabd8d761567d940c55cfe3.tar.gz dexon-solidity-26d47c7213ac8bb26fabd8d761567d940c55cfe3.tar.zst dexon-solidity-26d47c7213ac8bb26fabd8d761567d940c55cfe3.zip |
Split creating contracts
-rw-r--r-- | docs/contracts.rst | 118 | ||||
-rw-r--r-- | docs/contracts/creating-contracts.rst | 117 |
2 files changed, 118 insertions, 117 deletions
diff --git a/docs/contracts.rst b/docs/contracts.rst index 6d31ad82..bdf6902d 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -12,123 +12,7 @@ variables. Calling a function on a different contract (instance) will perform an EVM function call and thus switch the context such that state variables are inaccessible. -.. index:: ! contract;creation, constructor - -****************** -Creating Contracts -****************** - -Contracts can be created "from outside" via Ethereum transactions or from within Solidity contracts. - -IDEs, such as `Remix <https://remix.ethereum.org/>`_, make the creation process seamless using UI elements. - -Creating contracts programmatically on Ethereum is best done via using the JavaScript API `web3.js <https://github.com/ethereum/web3.js>`_. -It has a function called `web3.eth.Contract <https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#new-contract>`_ -to facilitate contract creation. - -When a contract is created, its constructor_ (a function declared with the ``constructor`` keyword) is executed once. - -A constructor is optional. Only one constructor is allowed, which means -overloading is not supported. - -After the constructor has executed, the final code of the contract is deployed to the -blockchain. This code includes all public and external functions and all functions -that are reachable from there through function calls. The deployed code does not -include the constructor code or internal functions only called from the constructor. - -.. index:: constructor;arguments - -Internally, constructor arguments are passed :ref:`ABI encoded <ABI>` after the code of -the contract itself, but you do not have to care about this if you use ``web3.js``. - -If a contract wants to create another contract, the source code -(and the binary) of the created contract has to be known to the creator. -This means that cyclic creation dependencies are impossible. - -:: - - pragma solidity >=0.4.22 <0.6.0; - - contract OwnedToken { - // `TokenCreator` is a contract type that is defined below. - // It is fine to reference it as long as it is not used - // to create a new contract. - TokenCreator creator; - address owner; - bytes32 name; - - // This is the constructor which registers the - // creator and the assigned name. - constructor(bytes32 _name) public { - // State variables are accessed via their name - // and not via e.g. `this.owner`. Functions can - // be accessed directly or through `this.f`, - // but the latter provides an external view - // to the function. Especially in the constructor, - // you should not access functions externally, - // because the function does not exist yet. - // See the next section for details. - owner = msg.sender; - - // We do an explicit type conversion from `address` - // to `TokenCreator` and assume that the type of - // the calling contract is `TokenCreator`, there is - // no real way to check that. - creator = TokenCreator(msg.sender); - name = _name; - } - - function changeName(bytes32 newName) public { - // Only the creator can alter the name -- - // the comparison is possible since contracts - // are explicitly convertible to addresses. - if (msg.sender == address(creator)) - name = newName; - } - - function transfer(address newOwner) public { - // Only the current owner can transfer the token. - if (msg.sender != owner) return; - - // We ask the creator contract if the transfer - // should proceed by using a function of the - // `TokenCreator` contract defined below. If - // the call fails (e.g. due to out-of-gas), - // the execution also fails here. - if (creator.isTokenTransferOK(owner, newOwner)) - owner = newOwner; - } - } - - contract TokenCreator { - function createToken(bytes32 name) - public - returns (OwnedToken tokenAddress) - { - // Create a new `Token` contract and return its address. - // From the JavaScript side, the return type is - // `address`, as this is the closest type available in - // the ABI. - return new OwnedToken(name); - } - - function changeName(OwnedToken tokenAddress, bytes32 name) public { - // Again, the external type of `tokenAddress` is - // simply `address`. - tokenAddress.changeName(name); - } - - // Perform checks to determine if transferring a token to the - // `OwnedToken` contract should proceed - function isTokenTransferOK(address currentOwner, address newOwner) - public - pure - returns (bool ok) - { - // Check an arbitrary condition to see if transfer should proceed - return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f; - } - } +.. include:: contracts/creating-contracts.rst .. index:: ! visibility, external, public, private, internal diff --git a/docs/contracts/creating-contracts.rst b/docs/contracts/creating-contracts.rst new file mode 100644 index 00000000..981243b1 --- /dev/null +++ b/docs/contracts/creating-contracts.rst @@ -0,0 +1,117 @@ +.. index:: ! contract;creation, constructor + +****************** +Creating Contracts +****************** + +Contracts can be created "from outside" via Ethereum transactions or from within Solidity contracts. + +IDEs, such as `Remix <https://remix.ethereum.org/>`_, make the creation process seamless using UI elements. + +Creating contracts programmatically on Ethereum is best done via using the JavaScript API `web3.js <https://github.com/ethereum/web3.js>`_. +It has a function called `web3.eth.Contract <https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#new-contract>`_ +to facilitate contract creation. + +When a contract is created, its :ref:`constructor <constructor>` (a function declared with the ``constructor`` keyword) is executed once. + +A constructor is optional. Only one constructor is allowed, which means +overloading is not supported. + +After the constructor has executed, the final code of the contract is deployed to the +blockchain. This code includes all public and external functions and all functions +that are reachable from there through function calls. The deployed code does not +include the constructor code or internal functions only called from the constructor. + +.. index:: constructor;arguments + +Internally, constructor arguments are passed :ref:`ABI encoded <ABI>` after the code of +the contract itself, but you do not have to care about this if you use ``web3.js``. + +If a contract wants to create another contract, the source code +(and the binary) of the created contract has to be known to the creator. +This means that cyclic creation dependencies are impossible. + +:: + + pragma solidity >=0.4.22 <0.6.0; + + contract OwnedToken { + // `TokenCreator` is a contract type that is defined below. + // It is fine to reference it as long as it is not used + // to create a new contract. + TokenCreator creator; + address owner; + bytes32 name; + + // This is the constructor which registers the + // creator and the assigned name. + constructor(bytes32 _name) public { + // State variables are accessed via their name + // and not via e.g. `this.owner`. Functions can + // be accessed directly or through `this.f`, + // but the latter provides an external view + // to the function. Especially in the constructor, + // you should not access functions externally, + // because the function does not exist yet. + // See the next section for details. + owner = msg.sender; + + // We do an explicit type conversion from `address` + // to `TokenCreator` and assume that the type of + // the calling contract is `TokenCreator`, there is + // no real way to check that. + creator = TokenCreator(msg.sender); + name = _name; + } + + function changeName(bytes32 newName) public { + // Only the creator can alter the name -- + // the comparison is possible since contracts + // are explicitly convertible to addresses. + if (msg.sender == address(creator)) + name = newName; + } + + function transfer(address newOwner) public { + // Only the current owner can transfer the token. + if (msg.sender != owner) return; + + // We ask the creator contract if the transfer + // should proceed by using a function of the + // `TokenCreator` contract defined below. If + // the call fails (e.g. due to out-of-gas), + // the execution also fails here. + if (creator.isTokenTransferOK(owner, newOwner)) + owner = newOwner; + } + } + + contract TokenCreator { + function createToken(bytes32 name) + public + returns (OwnedToken tokenAddress) + { + // Create a new `Token` contract and return its address. + // From the JavaScript side, the return type is + // `address`, as this is the closest type available in + // the ABI. + return new OwnedToken(name); + } + + function changeName(OwnedToken tokenAddress, bytes32 name) public { + // Again, the external type of `tokenAddress` is + // simply `address`. + tokenAddress.changeName(name); + } + + // Perform checks to determine if transferring a token to the + // `OwnedToken` contract should proceed + function isTokenTransferOK(address currentOwner, address newOwner) + public + pure + returns (bool ok) + { + // Check an arbitrary condition to see if transfer should proceed + return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f; + } + } |