aboutsummaryrefslogtreecommitdiffstats
path: root/docs/contracts
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2019-01-08 00:57:04 +0800
committerGitHub <noreply@github.com>2019-01-08 00:57:04 +0800
commit6888e08ef8ebcc1b70c429d832c7300a3890bfd9 (patch)
treeeb0c219af0d11ddef7888c10ea5a860f7fcf3d22 /docs/contracts
parent40e1283d728b0f456bb8d23b73c7c3953004edfb (diff)
parent3503f3809d3fac509914234029021bd33127516e (diff)
downloaddexon-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.rst117
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;
+ }
+ }