Skip to main content

Solidity Contracts Examples

This set of smart-contract samples illustrates standard functionality of smart-contracts developed in Solidity, starting with very basic and gradually evolving into code snippets, which may come handy in production smart-contracts.

  • You can find a list of all the contracts listed in this EverX (formerly TON Labs) repository.

1. Accumulator : persistent storage

Smart-contracts deployed to the blockchain store their state variables in a persistent storage. Call Accumulator.add(uint value). It adds value to its state variable sum. Resulting state of the account can be examined by conventional means.

2. StorageClient: calling another contract

Contracts can also call other remote contracts. Call storageAddress) to invoke a public function of another contract. The remote contract UintStorage saves the integer value of the argument and the caller address in its state variables.

3. Borrower: EVER transfer

This sample demonstrates how currency transfer works. Call Borrower.askForALoan(Loaner loanerAddress, uint amount). This requests amount of currency from the contract deployed at the specified address. The remote contract LoanerContract transfers amount of currency to the caller via msg.sender.transfer(amount). Each contract has an internal transaction counter. The counter value increases with each transaction and is stored in the persistent memory.

4. CurrencyExchange: callback implementation

Call CurrencyExchange.updateExchangeRate(address bankAddress, uint16 code). This function allows interacting with a remote contract by calling its function: ICentralBank.GetExchangeRate(uint16 code). The remote contract CentralBank obtains caller's address via msg.sender and performs a callback.

  1. Bank: loan interaction between Bank and BankClient

Call Bank.setAllowance(address bankClientAddress, uint amount). Bank stores information about loan allowances and current debts for different contracts. This data is recorded in the following state variable: mapping(address => CreditInfo) clientDB;
A contract owner is supposed to call the setAllowance() function to specify limits.

BankClient is a client that can interact with Bank.

Call BankClient.getMyCredit(IBank bank). This function calls the remote contract Bank to receive allowed credit limit via Bank invoking the callback function setCreditLimit(uint limit).

Call BankClient.askForALoan(IBank bank, uint amount). This function call the remote contract Bank to get an amount of credit. According to the current credit info of the BankClient contract Bank will approve the credit via calling the callback function "receiveLoan(uint n_totalDebt)" or refuse the credit via calling the callback function refusalCallback(uint availableLimit). receiveLoan function also obtains balance of the contract via address(this).balance and balance of the inbound message via msg.value and saves them in state variables. refusalCallback function saves the argument (available credit limit) in the state variable.

6. DataBase: exchange of different types of values

One of contract functions call allows sending to the DataBaseClient different values:

  • uint64 array;
  • five uint arrays;
  • five uint256;
  • struct array.

7. Giver: simple giver contract

This sample shows usage of different types of currency transactions and usage of a fallback function.

Call Giver.transferToAddress(address payable destination, uint amount) or Giver.do_tvm_transfer(address payable remote_addr, uint128 ton_value, bool bounce, uint16 sendrawmsg_flag) to perform a currency transaction. Call Giver.transferToCrashContract(address payable destination, uint amount) to implement a crash during transaction. That will cause an exception in CrashContract and Giver's contract fallback function calling. Call Giver.transferToAbstractContract(address payable destination, uint amount) with a non-existent address AbstractContract will also call a fallback function of Giver.

8. Kamikaze: selfdestruct function

Call Kamikaze.sendAllMoney(address anotherContract). This function destroys the contract and sends all its funds to the specified address of Heir contract.

9. PiggyBank: Piggy bank with two clients

This sample consists of 3 contracts:

  • PiggyBank - piggy bank itself.
  • PiggyBank_Owner - piggy bank's owner - valid user, who can add to piggy bank's deposit and withdraw.
  • PiggyBank_Stranger - stranger - invalid user, who can add to piggy bank but can not withdraw.

Call PiggyBank_Owner.addToDeposit(PiggyBank bankAddress, uint amount) or PiggyBank_Stranger.addToDeposit(PiggyBank bankAddress, uint amount) to transfer EVERs from the contract to PiggyBank.

Call PiggyBank_Owner.withdrawDeposit(PiggyBank bankAddress) of PiggyBank_Stranger.withdrawDeposit(PiggyBank bankAddress) to try to withdraw the deposit from PiggyBank. Transfer would occur only for the owner.

10. Wallet: Simple wallet

Call Wallet.sendTransaction(address payable dest, uint128 value, bool bounce). This function allows transferring EVERs to the specified account.

11. ContractDeployer: Deploy Contract from contract via new.

The way to get arguments for deploying is described How to deploy contract from contract.

12. BadContract: Contract upgrade

Contract code could be changed via using tvm.setcode function. It could be useful for fixing errors and functionality updating. In that example we have a BadContract (it is a PiggyBank contract with added upgrade functionality) and new version of that contract NewVersion.

Call "PiggyBank.setCode(TvmCell memory newcode)" with argument that contains code of NewVersion contract to change the code of the contract.

13. BankCollector: Mapping methods

Developer can work with mappings using methods: fetch, min, next. This methods allow to check existence of the key, obtain lexicographically minimal key and lexicographically next key respectively.

14. CustomReplayProtection: Custom replay protection

Developer can redefine function afterSignatureCheck to create his own replay protection function instead of default one.

15. MessageSender: Message construction and parsing

Developer can use TVM specific types to build message manually and special api function tvm.sendrawmsg() to send it. Contract MessageSender performs such actions to build a message which will call the function of another contract MessageReceiver. MessageReceiver also shows how to parse a cell.

16. onBounceHandler: Working with bounced messages

Developer can define onBounce function to work with bounced messages. If an error occurs while message transferring or handling it can be bounced back to the source contract. This sample demonstrates how you can handle such bounced message.

17. low_level: Constructor message structure

18. Interfaces, OrderClient, OrderDatabase: Order Book

Interface.sol - interface of DataBase and Client Contract.

OrderClient.sol - contract that can create new orders in OrderDatabase contract.

OrderDtatabase.sol - stores order information, creates an order, changes the database, etc.

19. Casino, CasinoClient, CasinoOwner, CasinoInterfaces: Casino

Casino - Casino roulette smart contract.

CasinoInterfaces.sol - interface of the Casino contract.

CasinoOwner.sol, CasinoClient.sol - Casino owner smart contracts.

20. Bomber, Interface, Sink: Bomber

21. Self_deploy: Self Deployer

This sample shows how the contract can deploy another contract of the same type.

22. Sender, Sink: Sender

Generates cell which contains message which calls another contract by internal outbound message. Saves received value in state variable.

23. rawReserve, sender: Reserver

A contract that reserves a certain amount of EVER from the remaining balance of the account: exactly,at most,or all but.

24. ISquareProvider, LengthProvider, SquareProvider, WidthProvider: Rectangle square

25. Config: Function arguments specification

Sometimes it can be not obvious in which way function arguments should be specified, especially if it is a large structure with different and complex fields. It is generally described in abi doc. And this example was made to help users clear this moment.