diff options
author | chriseth <chris@ethereum.org> | 2019-01-08 00:57:04 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-08 00:57:04 +0800 |
commit | 6888e08ef8ebcc1b70c429d832c7300a3890bfd9 (patch) | |
tree | eb0c219af0d11ddef7888c10ea5a860f7fcf3d22 /docs/contracts | |
parent | 40e1283d728b0f456bb8d23b73c7c3953004edfb (diff) | |
parent | 3503f3809d3fac509914234029021bd33127516e (diff) | |
download | dexon-solidity-6888e08ef8ebcc1b70c429d832c7300a3890bfd9.tar.gz dexon-solidity-6888e08ef8ebcc1b70c429d832c7300a3890bfd9.tar.zst dexon-solidity-6888e08ef8ebcc1b70c429d832c7300a3890bfd9.zip |
Merge pull request #5739 from ethereum/docs-split-create-contracts
[DOCS] Split creating contracts
Diffstat (limited to 'docs/contracts')
-rw-r--r-- | docs/contracts/creating-contracts.rst | 117 |
1 files changed, 117 insertions, 0 deletions
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; + } + } |