A okosszerződések anatómiája
Utolsó módosítás: @robertdosa(opens in a new tab), 2024. június 14.
Az okosszerződés egy olyan program, mely egy cím alatt fut az Ethereumon. Adatokból és függvényekből állnak, melyeket végre lehet hajtani bemenő tranzakciók által. Ez az áttekintés az okosszerződések felépítéséről szól.
Előfeltételek
Először tekintse meg az okosszerződésekről szóló cikket. Ez a dokumentum feltételezi, hogy már jártas a programozási nyelvekben, mint a JavaScript vagy a Python.
Adat
Minden szerződésadatot hozzá kell rendelni egy lokációhoz, mely lehet a storage
vagy a memory
. Költséges a tárhelyet módosítani egy okosszerződésben, tehát érdemes fontolóra venni, hogy hol legyen az adat.
Tárhely
Az állandó adatokat tárolásnak nevezzük, és állapotváltozók reprezentálják őket. Ezeket az értékeket permanensen a blokkláncon tároljuk. Deklarálnia kell a típust, hogy a szerződés számon tudja tartani, hogy mekkora tárhelyre lesz szüksége a blokkláncon az átfordításkor.
1// Solidity példa2contract SimpleStorage {3 uint storedData; // Állapotváltozó4 // ...5}Másolás
1# Vyper példa2storedData: int128Másolás
Ha Ön programozott már objektumorientált nyelven, akkor a legtöbb típus valószínűleg ismerős lesz. Ugyanakkor az address
típus új lesz, ha még csak most ismerkedik az Ethereum fejlesztéssel.
Az address
típus egy Ethereum címet tud tárolni, mely 20 bájttal vagy 160 bittel egyenlő. Hexadecimális értéket ad vissza vezető 0x-szel.
A többi típus:
- boolean
- egész (integer)
- fixpontos szám
- fix méretű bájttömb
- dinamikus méretű bájttömb
- Racionális és egész szám literálok
- String literálok
- Hexadecimális literálok
- Enum
További magyarázatért tekintse meg az alábbi dokumentumokat:
Memória
Memóriaváltozóknak nevezzük azokat az értékeket, melyek csak a szerződésfunkció végrehajtása alatt tárolódnak. Mivel nem kell őket permanensen a blokkláncon tárolni, így sokkal olcsóbb a használatuk.
Tudjon meg többet az EVM adattárolási módszeréről a Solidity dokumentációból(opens in a new tab) (a „Storage, Memory and the Stack” szekcióból).
Környezeti változók
A szerződésben meghatározott változók mellett van néhány speciális globális változó is. Elsősorban a blokklánccal vagy az aktuális tranzakcióval kapcsolatos információk nyújtására szolgálnak.
Példák:
Tul. | Állapotváltozó | Leírás |
---|---|---|
block.timestamp | uint256 | Jelenlegi blokk korszak időbélyege |
msg.sender | address | Az üzenet küldője (jelenlegi hívás) |
Függvények
A legegyszerűbben megfogalmazva, a függvények információkat kaphatnak vagy információkat állíthatnak be válaszul a bejövő tranzakciókra.
Kétfajta függvényhívás létezik:
internal
– ezek nem okoznak EVM hívást- A belső (internal) függvényeket és állapotváltozókat csak belülről lehet elérni (vagyis a jelenlegi szerződésből vagy a származtatott szerződésekből)
external
– ezek EVM hívást okoznak- A külső (external) függvények a szerződés felületének részei, mely azt jelenti, hogy meg lehet őket hívni más szerződésekből vagy tranzakciókon keresztül. Egy külső függvény
f
kódját nem lehet belülről meghívni (vagyis azf()
nem működik, de athis.f()
igen).
- A külső (external) függvények a szerződés felületének részei, mely azt jelenti, hogy meg lehet őket hívni más szerződésekből vagy tranzakciókon keresztül. Egy külső függvény
Ezenkívül lehetnek public
vagy private
típusúak is
- a
public
függvényeket belülről lehet meghívni vagy kívülről üzenetek által - a
private
függvények csak abban a szerződésben láthatóak, amiben definiálták őket, a származtatott szerződésekben nem
A függvények és az állapotváltozók is lehetnek publikusak vagy privátak
Íme egy függvény, mely egy állapotváltozó értékét állítja be egy szerződésben:
1// Solidity példa2function update_name(string value) public {3 dapp_name = value;4}Másolás
- A
string
típusúvalue
paraméter kerül be a függvénybe:update_name
- Ez
public
módon lett deklarálva, így mindenki hozzáfér - Nem
view
módon lett deklarálva, így módosíthatja a szerződésállapotot
Nézet (view) függvények
Ezek a függvények azt ígérik, hogy nem módosítják a szerződés adatainak állapotát. Általános példák a „getter” függvények – ezeket használhatja például egy felhasználó egyenlegének lekérdezésére.
1// Solidity példa2function balanceOf(address _owner) public view returns (uint256 _balance) {3 return ownerPizzaCount[_owner];4}Másolás
1dappName: public(string)23@view4@public5def readName() -> string:6 return dappNameMásolás
Mi számít állapotmódosításnak:
- Állapotváltozókba írás.
- Események kibocsátása(opens in a new tab).
- Másik szerződés létrehozás(opens in a new tab).
- A
selfdestruct
használata. - Ether küldése hívásokkal.
- Bármely függvény meghívása, mely nincs
view
vagypure
jelöléssel ellátva. - Alacsony szintű hívások.
- Egysoros assembly használata, mely bizonyos opkódot tartalmaz.
Konstruktor függvények
A constructor
csak egyszer fut le, amikor a szerződést először telepítik. Mint a constructor
számos osztályalapú programozási nyelv esetében, ezek a függvények gyakran inicializálják az állapotváltozókat a meghatározott értékeikre.
1// Solidity példa2// Inicializálja a szerződés adatait, beállítja az 'owner-t'3// a szerződés létrehozó címére.4constructor() public {5 // Minden okosszerződés külső tranzakciókra hagyatkozik a függvényeik végrehajtására.6 // az `msg` globális változó, mely az adott tranzakcióhoz tartozó adatot tartalmaz,7 // mint a küldő címe és az ETH mennyisége a tranzakcióban.8 // Több infó: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties9 owner = msg.sender;10}Összes megjelenítéseMásolás
1# Vyper példa23@external4def __init__(_beneficiary: address, _bidding_time: uint256):5 self.beneficiary = _beneficiary6 self.auctionStart = block.timestamp7 self.auctionEnd = self.auctionStart + _bidding_timeMásolás
Beépített függvények
A szerződésben meghatározott függvények és változók mellett van néhány speciális beépített függvény is. A legnyilvánvalóbb példák:
address.send()
– Soliditysend(address)
– Vyper
Ez lehetőséget ad a szerződéseknek, hogy ETH-t küldjenek más számláknak.
Függvények írása
A függvénynek szüksége van:
- egy paraméterváltozóra és egy típusra (ha elfogad paramétereket)
- a belső/külső deklarációra
- a pure/view/payable deklarációra
- a visszatérítési érték típusára (ha van visszatérítési értéke)
1pragma solidity >=0.4.0 <=0.6.0;23contract ExampleDapp {4 string dapp_name; // state variable56 // Called when the contract is deployed and initializes the value7 constructor() public {8 dapp_name = "My Example dapp";9 }1011 // Get Function12 function read_name() public view returns(string) {13 return dapp_name;14 }1516 // Set Function17 function update_name(string value) public {18 dapp_name = value;19 }20}Összes megjelenítéseMásolás
Egy kész szerződés nagyjából így nézne ki. Itt a constructor
függvény biztosítja a dapp_name
változó kezdeti értékét.
Események és naplózások
Az eseményeken keresztül tud kommunikálni az okosszerződés és a frontend vagy más feliratkozó alkalmazás. Amikor egy tranzakciót kibányásztak, az okosszerződések eseményeket bocsáthatnak ki és naplófájlokat írhatnak a blokkláncra, melyet a frontend fel tud dolgozni.
Jegyzetekkel ellátott példák
Íme néhány példa, amelyet Solidity-ben írtak. Ha szeretne megismerkedni a kóddal, akkor kipróbálhatja a Remixben(opens in a new tab).
Hello world
1// A Solidity verziószámát írja elő szemantikailag.2// Több információ: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma3pragma solidity ^0.5.10;45// Egy `HelloWorld` nevű szerződés definiálása.6// A szerződés egy függvények és adatok (az állapota) gyűjteménye.7// Telepítés után a szerződés egy bizonyos címen él az Ethereum blokkláncon.8//További információ: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html9contract HelloWorld {1011 // Deklarálja a `string` típusú `message` állapotváltozót.12 // Az állapotváltozók olyan változók, melyeknek értékei permanensen tárolódnak a szerződés tárhelyén.13 // A `public` kulcsszó lehetővé teszi a változó szerződésen kívüli elérését14 // és függvényt hoz létre, mellyel más szerződések vagy kliensek le tudják kérdezni az értéket.15 string public message;1617 // Más osztály alapú nyelvhez hasonlóan a konstruktor egy18 // speciális függvény, mely csak egyszer fut le a szerződés létrehozáskor.19 // A konstruktorokat az szerződés adatainak inicializálásra lehet használni.20 // További információ: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors21 constructor(string memory initMessage) public {22 // Az `initMessage` string paramétert fogadja el és beállítja23 // a szerződés `message` tárhely változójába).24 message = initMessage;25 }2627 // Egy publikus függvény, mely egy string paramétert fogad el28 // és frissíti a `message` tárhely változót.29 function update(string memory newMessage) public {30 message = newMessage;31 }32}Összes megjelenítéseMásolás
Token
1pragma solidity ^0.5.10;23contract Token {4 // Egy `address` olyan, mint egy email cím - az Ethereum számlák beazonosítására szolgál.5 // A címek okosszerződéseket vagy külső (felhasználói) számlákat jelölnek.6 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#address7 address public owner;89 // A `mapping` lényegében egy hash tábla adatszerkezet.10 // Ez a `mapping` egy unsigned integert (a token egyenleget) rendel hozzá egy címhez (a token tartóhoz).11 // További információ: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types12 mapping (address => uint) public balances;1314 // Az eseményekkel lehet tevékenységet logolni a blokkláncon.15 // Az Ethereum kliensek figyelhetik az eseményeket, hogy reagáljanak az szerződés állapotváltozásokra.16 // További információ: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events17 event Transfer(address from, address to, uint amount);1819 // Inicializálja a szerződés adatot, beállítja az `owner`20 // változót a szerződés létrehozó címére.21 constructor() public {22 // Minden okosszerződés külső tranzakciókra hagyatkozik a függvényeik végrehajtására.23 // az `msg` globális változó, mely az adott tranzakcióhoz tartozó adatot tartalmaz,24 // mint a küldő címe és az ETH mennyisége a tranzakcióban.25 //További információ: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties26 owner = msg.sender;27 }2829 // Új tokeneket hoz létre és elküldi egy címre.30 function mint(address receiver, uint amount) public {31 // A `require` egy kontrol struktúra, mely bizonyos feltételek betartatására szolgál.32 // Ha a `require` állítás `false` értéket ad, egy kivétel triggerelődik,33 // mely visszaállít minden állapotváltozást a jelenlegi hívás alatt.34 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions3536 // Only the contract owner can call this function37 require(msg.sender == owner, "You are not the owner.");3839 // Enforces a maximum amount of tokens40 require(amount < 1e60, "Maximum issuance exceeded");4142 // Increases the balance of `receiver` by `amount`43 balances[receiver] += amount;44 }4546 // Sends an amount of existing tokens from any caller to an address.47 function transfer(address receiver, uint amount) public {48 // A küldőnek elég tokennel kell rendelkeznie49 require(amount <= balances[msg.sender], "Insufficient balance.");5051 // Beállítja a token a két cím token mennyiségét52 balances[msg.sender] -= amount;53 balances[receiver] += amount;5455 // Kibocsájtja a korábban definiált eseményt56 emit Transfer(msg.sender, receiver, amount);57 }58}Összes megjelenítéseMásolás
Egyedi digitális eszköz
1pragma solidity ^0.5.10;23// Szimbólumokat importál be más fájlokból a jelenlegi szerződésbe.4// Ebben az esetben egy pár segítő szerződést az OpenZeppelinről.5// További információ: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files67import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol";8import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";9import "../node_modules/@openzeppelin/contracts/introspection/ERC165.sol";10import "../node_modules/@openzeppelin/contracts/math/SafeMath.sol";1112// Az `is` kulcsszót használjuk, hogy külső szerződések függvényeit és kulcsszavait örököltessük.13// Ebben az esetben, `CryptoPizza` örököl az `IERC721` és az `ERC165` szerződésekből.14// További információ: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance15contract CryptoPizza is IERC721, ERC165 {16 // Az OpenZeppelin SafeMath könyvtárát használja aritmetikai számítások biztonságos elvégzésére.17 // További információ: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath18 using SafeMath for uint256;1920 // A konstans állapotváltozók a Solidity-ben hasonlóak más nyelvekhez21 // de a fordítás ideje alatt konstans kifejezésből kell hozzárendelni.22 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables23 uint256 constant dnaDigits = 10;24 uint256 constant dnaModulus = 10 ** dnaDigits;25 bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;2627 // Struct types let you define your own type28 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs29 struct Pizza {30 string name;31 uint256 dna;32 }3334 // Creates an empty array of Pizza structs35 Pizza[] public pizzas;3637 // Mapping from pizza ID to its owner's address38 mapping(uint256 => address) public pizzaToOwner;3940 // Mapping from owner's address to number of owned token41 mapping(address => uint256) public ownerPizzaCount;4243 // Mapping from token ID to approved address44 mapping(uint256 => address) pizzaApprovals;4546 // You can nest mappings, this example maps owner to operator approvals47 mapping(address => mapping(address => bool)) private operatorApprovals;4849 // Internal function to create a random Pizza from string (name) and DNA50 function _createPizza(string memory _name, uint256 _dna)51 // The `internal` keyword means this function is only visible52 // within this contract and contracts that derive this contract53 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters54 internal55 // `isUnique` is a function modifier that checks if the pizza already exists56 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers57 isUnique(_name, _dna)58 {59 // Adds Pizza to array of Pizzas and get id60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);6162 // Checks that Pizza owner is the same as current user63 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions6465 // note that address(0) is the zero address,66 // indicating that pizza[id] is not yet allocated to a particular user.6768 assert(pizzaToOwner[id] == address(0));6970 // Maps the Pizza to the owner71 pizzaToOwner[id] = msg.sender;72 ownerPizzaCount[msg.sender] = SafeMath.add(73 ownerPizzaCount[msg.sender],74 175 );76 }7778 // Creates a random Pizza from string (name)79 function createRandomPizza(string memory _name) public {80 uint256 randDna = generateRandomDna(_name, msg.sender);81 _createPizza(_name, randDna);82 }8384 // Generates random DNA from string (name) and address of the owner (creator)85 function generateRandomDna(string memory _str, address _owner)86 public87 // Functions marked as `pure` promise not to read from or modify the state88 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions89 pure90 returns (uint256)91 {92 // Generates random uint from string (name) + address (owner)93 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +94 uint256(_owner);95 rand = rand % dnaModulus;96 return rand;97 }9899 // Returns array of Pizzas found by owner100 function getPizzasByOwner(address _owner)101 public102 // Functions marked as `view` promise not to modify state103 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions104 view105 returns (uint256[] memory)106 {107 // Uses the `memory` storage location to store values only for the108 // lifecycle of this function call.109 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack110 uint256[] memory result = new uint256[](ownerPizzaCount[_owner]);111 uint256 counter = 0;112 for (uint256 i = 0; i < pizzas.length; i++) {113 if (pizzaToOwner[i] == _owner) {114 result[counter] = i;115 counter++;116 }117 }118 return result;119 }120121 // Transfers Pizza and ownership to other address122 function transferFrom(address _from, address _to, uint256 _pizzaId) public {123 require(_from != address(0) && _to != address(0), "Invalid address.");124 require(_exists(_pizzaId), "Pizza does not exist.");125 require(_from != _to, "Cannot transfer to the same address.");126 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");127128 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);129 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);130 pizzaToOwner[_pizzaId] = _to;131132 // Emits event defined in the imported IERC721 contract133 emit Transfer(_from, _to, _pizzaId);134 _clearApproval(_to, _pizzaId);135 }136137 /**138 * Safely transfers the ownership of a given token ID to another address139 * If the target address is a contract, it must implement `onERC721Received`,140 * which is called upon a safe transfer, and return the magic value141 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;142 * otherwise, the transfer is reverted.143 */144 function safeTransferFrom(address from, address to, uint256 pizzaId)145 public146 {147 // solium-disable-next-line arg-overflow148 this.safeTransferFrom(from, to, pizzaId, "");149 }150151 /**152 * Safely transfers the ownership of a given token ID to another address153 * If the target address is a contract, it must implement `onERC721Received`,154 * which is called upon a safe transfer, and return the magic value155 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;156 * otherwise, the transfer is reverted.157 */158 function safeTransferFrom(159 address from,160 address to,161 uint256 pizzaId,162 bytes memory _data163 ) public {164 this.transferFrom(from, to, pizzaId);165 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received.");166 }167168 /**169 * Internal function to invoke `onERC721Received` on a target address170 * The call is not executed if the target address is not a contract171 */172 function _checkOnERC721Received(173 address from,174 address to,175 uint256 pizzaId,176 bytes memory _data177 ) internal returns (bool) {178 if (!isContract(to)) {179 return true;180 }181182 bytes4 retval = IERC721Receiver(to).onERC721Received(183 msg.sender,184 from,185 pizzaId,186 _data187 );188 return (retval == _ERC721_RECEIVED);189 }190191 // Burns a Pizza - destroys Token completely192 // The `external` function modifier means this function is193 // part of the contract interface and other contracts can call it194 function burn(uint256 _pizzaId) external {195 require(msg.sender != address(0), "Invalid address.");196 require(_exists(_pizzaId), "Pizza does not exist.");197 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");198199 ownerPizzaCount[msg.sender] = SafeMath.sub(200 ownerPizzaCount[msg.sender],201 1202 );203 pizzaToOwner[_pizzaId] = address(0);204 }205206 // Returns count of Pizzas by address207 function balanceOf(address _owner) public view returns (uint256 _balance) {208 return ownerPizzaCount[_owner];209 }210211 // Returns owner of the Pizza found by id212 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {213 address owner = pizzaToOwner[_pizzaId];214 require(owner != address(0), "Invalid Pizza ID.");215 return owner;216 }217218 // Approves other address to transfer ownership of Pizza219 function approve(address _to, uint256 _pizzaId) public {220 require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner.");221 pizzaApprovals[_pizzaId] = _to;222 emit Approval(msg.sender, _to, _pizzaId);223 }224225 // Returns approved address for specific Pizza226 function getApproved(uint256 _pizzaId)227 public228 view229 returns (address operator)230 {231 require(_exists(_pizzaId), "Pizza does not exist.");232 return pizzaApprovals[_pizzaId];233 }234235 /**236 * Private function to clear current approval of a given token ID237 * Reverts if the given address is not indeed the owner of the token238 */239 function _clearApproval(address owner, uint256 _pizzaId) private {240 require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner.");241 require(_exists(_pizzaId), "Pizza does not exist.");242 if (pizzaApprovals[_pizzaId] != address(0)) {243 pizzaApprovals[_pizzaId] = address(0);244 }245 }246247 /*248 * Sets or unsets the approval of a given operator249 * An operator is allowed to transfer all tokens of the sender on their behalf250 */251 function setApprovalForAll(address to, bool approved) public {252 require(to != msg.sender, "Cannot approve own address");253 operatorApprovals[msg.sender][to] = approved;254 emit ApprovalForAll(msg.sender, to, approved);255 }256257 // Tells whether an operator is approved by a given owner258 function isApprovedForAll(address owner, address operator)259 public260 view261 returns (bool)262 {263 return operatorApprovals[owner][operator];264 }265266 // Takes ownership of Pizza - only for approved users267 function takeOwnership(uint256 _pizzaId) public {268 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");269 address owner = this.ownerOf(_pizzaId);270 this.transferFrom(owner, msg.sender, _pizzaId);271 }272273 // Checks if Pizza exists274 function _exists(uint256 pizzaId) internal view returns (bool) {275 address owner = pizzaToOwner[pizzaId];276 return owner != address(0);277 }278279 // Checks if address is owner or is approved to transfer Pizza280 function _isApprovedOrOwner(address spender, uint256 pizzaId)281 internal282 view283 returns (bool)284 {285 address owner = pizzaToOwner[pizzaId];286 // Disable solium check because of287 // https://github.com/duaraghav8/Solium/issues/175288 // solium-disable-next-line operator-whitespace289 return (spender == owner ||290 this.getApproved(pizzaId) == spender ||291 this.isApprovedForAll(owner, spender));292 }293294 // Check if Pizza is unique and doesn't exist yet295 modifier isUnique(string memory _name, uint256 _dna) {296 bool result = true;297 for (uint256 i = 0; i < pizzas.length; i++) {298 if (299 keccak256(abi.encodePacked(pizzas[i].name)) ==300 keccak256(abi.encodePacked(_name)) &&301 pizzas[i].dna == _dna302 ) {303 result = false;304 }305 }306 require(result, "Pizza with such name already exists.");307 _;308 }309310 // Returns whether the target address is a contract311 function isContract(address account) internal view returns (bool) {312 uint256 size;313 // Currently there is no better way to check if there is a contract in an address314 // than to check the size of the code at that address.315 // See https://ethereum.stackexchange.com/a/14016/36603316 // for more details about how this works.317 // TODO Check this again before the Serenity release, because all addresses will be318 // contracts then.319 // solium-disable-next-line security/no-inline-assembly320 assembly {321 size := extcodesize(account)322 }323 return size > 0;324 }325}Összes megjelenítéseMásolás
További olvasnivaló
Tekintse meg a Solidity és a Vyper dokumentációit az okosszerződések teljesebb áttekintésért:
Kapcsolódó témák
Kapcsolódó útmutatók
- A szerződések méretének csökkentése, hogy ne okozzon gondot a méretkorlát – Gyakorlati tanácsok az okosszerződés méretének redukálására.
- Okosszerződések adatnaplózása az események mentén – Bevezetés az okossszerződések eseményeibe, s azok használata az adatnaplózáshoz.
- Más szerződésekkel való interakció a Solidity által – Hogyan telepítsen okosszerződést egy létező szerződésből és kapcsolódjon azzal.