# Solidity
---
## [Solidity Compiler](https://github.com/ethereum/solidity)
converts object-oriented, high-level language to implement contract templates into simple binaries, assembly and various other related metadata
### pragma solidity
```javascript
pragma solidity >=0.4.0 <0.7.0; // only compatible with
// solidity compiler bigger or equal to v0.4.0
// but smaller than v0.7.0
```
(see [all compiler versions](https://github.com/ethereum/solc-bin/tree/gh-pages/bin))
---
# Simple `Coin` Contract Template
---
## Contract Template
### define State Variables
Are like a single slot in a database.
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address X; // declares a state variable X which can store
// an address of an external (="wallet") or contract **account**.
// Other accounts have no access to this state variable
}
```
**`X`** is of type **`address`** (=160-bit value that does not allow any arithmetic operations).
---
## Contract Template
### define Functions
* **`set`** and **`get` view** as part of **public** interface
* functions can take arguments and can return values
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address account;
// takes one argument `x` of type `address`
function set (address x) public { account = x; }
// `view` guarantees function to not change state
// (=read only of state)
// returns a value of type `address`
function get () public view returns (address) { return account; }
}
```
these functions can be used by other **`acounts`** to **set**/modify/alter or **get**/query/retrieve a value of a state variable.
---
## Contract Template
### Access Modifier
**`public`** keyword auto-generates a read access function for other accounts
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address public X; // behaves like:
// function X() public view returns (address) { return X; }
}
```
---
## Contract Template
### `mapping` data type
map key of type1 to value of type2 for later lookup
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address public minter;
mapping (address => uint) balances;
// type `uint` (=unsigned integer of 256 bits)
}
// lookup `balances[minter]` defaults to value `0` of type `uint`
// assign `balances[minter] = 123`
// => to map `minter` address to uint `123`
// lookup `balances[minter]` now returns `123` of type `uint`
```
All keys by default map to all zeros byte-representation values and listing all is not possible
---
## Contract Template
### `mapping` data type
map key of type1 to value of type2 for later lookup
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address public minter;
mapping (address => uint) public balances;
// function balances(address X) external view returns (uint) {
// return balances[X];
// }
}
```
Using **`public`** on a **`mapping`** auto-generates a more complex read access function for other accounts to query the balance of a single account
* e.g. `balances(minter)` => `123`
---
## Contract Template
### global variables
```javascript
// sender of the message (current call)
msg.sender (address payable)
// MORE:
// number of wei sent with the message
msg.value (uint)
msg.data (bytes calldata) // complete calldata
// first four bytes of the calldata (i.e. function identifier)
msg.sig (bytes4)
// current block timestamp (alias for block.timestamp)
now (uint)
gasleft() returns (uint256) // remaining gas
// gas price of the transaction
tx.gasprice (uint)
// sender of the transaction (full call chain)
tx.origin (address payable)
// hash of one of the most recent 256 blocks, but not current
blockhash(uint blockNumber) returns (bytes32)
block.coinbase (address payable) // current block miner’s address
block.difficulty (uint) // current block difficulty
block.gaslimit (uint) // current block gaslimit
block.number (uint) // current block number
// current block timestamp as seconds since unix epoch
block.timestamp (uint)
```
---
## Contract Template
### constructor
Constructor function runs only once when the contract is published
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address public minter; // will store address of publisher
mapping (address => uint) public balances;
// executes ONLY once at contract creation time
constructor () public {
minter = msg.sender; // `msg.sender` always refers to the
// account address which sent the current transaction
}
}
```
---
## Contract Template
### declare events
declares an **`event`** which can be emitted and allows clients (e.g. dapps) to react
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address public minter;
mapping (address => uint) public balances;
constructor() public { minter = msg.sender; }
event Sent(address from, address to, uint amount);
}
```
---
## Contract Template
### emit events
Event listeners receive emitted arguments
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address public minter;
mapping (address => uint) public balances;
constructor() public { minter = msg.sender; }
event Sent(address from, address to, uint amount);
// Sends an amount of existing coins
// from any caller to an address
function send (address receiver, uint amount) public {
balances[msg.sender] -= amount;
// short for: balances[msg.sender] = balances[msg.sender] - amount;
balances[receiver] += amount;
// short for: balances[receiver] = balances[receiver] + amount;
emit Sent(msg.sender, receiver, amount);
// arguments (`from`,`to`,`amount`) to track transactions
}
// Sends an amount of newly created coins to an address
// Can only be called by the contract creator
function mint (address receiver, uint amount) public {
balances[receiver] += amount;
// short for: balances[receiver] = balances[receiver] + amount;
}
}
```
---
## Dapp
### event listening
```javascript
// ethers
// abi
// bytecode
var currentProvider = window.web3.currentProvider
var provider = new ethers.providers.Web3Provider(currentProvider)
var contractAddress = '' // paste contract's address
var dapp = new ethers.Contract(contractAddress, abi, provider)
async function getEvent () {
dapp.on("Sent", (from, to, event) => {
console.log(`From (address): ${from}`)
console.log(`To (address): ${to}`)
console.log(`Event: ${event}`)
})
}
getEvent()
```
---
## Dapp
### calling functions
```javascript
// ...
const receiver = '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
const amount = 500
async function dapp (contract) {
await contract.mint(receiver, amount)
const currentValue = await contract.balances(receiver)
console.log(currentValue) // => 500
}
```
---
## Contract Template
### `require` guard
If `"1st argument"` of `require` is `false`,
execution ends and all state and ether balance changes are reverted.
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address public minter;
mapping (address => uint) public balances;
constructor() public { minter = msg.sender; }
event Sent(address from, address to, uint amount);
function send (address receiver, uint amount) public {
// use `require` to check if functions are called as intended.
// A 2nd argument can provide explanations about whats wrong.
require(amount <= balances[msg.sender], "Not enough funds.");
// guard: can be used by anyone who has the amount of tokens to send
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
function mint (address receiver, uint amount) public {
require(msg.sender == minter);
// guard: ensures only the contract publisher can call mint
require(amount < 1e60);
// guard: prevents overflow errors in the future
balances[receiver] += amount; // assign tokens to address
}
}
```
---
## Demo Time
copy to open in [play-ed](https://playproject.io/play-ed)
```javascript
pragma solidity >=0.4.0 <0.7.0;
contract Coin {
address public minter;
mapping (address => uint) public balances;
constructor() public { minter = msg.sender; }
event Sent(address from, address to, uint amount);
function send (address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Not enough funds.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
function mint (address receiver, uint amount) public {
require(msg.sender == minter);
require(amount < 1e60);
balances[receiver] += amount;
}
}
```
---
# Simple `Ballot` Contract Template
---
## Contract Template
### `struct` type & `bool` type & [NatSpec](https://solidity.readthedocs.io/en/latest/natspec-format.html#natspec-format)
```javascript
pragma solidity >=0.4.22 <0.7.0;
// NatSpec uses `///` to include informative comments in compiler output
// see: https://solidity.readthedocs.io/en/latest/natspec-format.html#tags
/// @title Transparent voting with automated vote counting.
contract Ballot { // 1 contract per ballot with option short-names
address public chairperson;
// `struct` declares a new complex type to be used for variables later
struct Voter { // represents a single voter.
uint weight; // weight 0 prevents from voting
bool voted; // if true, that person already voted
uint vote; // index of the voted proposal
}
}
```
**`bool`** can only store one of two values at a time (**`true`** or **`false`**)
---
## Contract Template
### `bytes32` type
```javascript
pragma solidity >=0.4.22 <0.7.0;
contract Ballot {
address public chairperson;
struct Voter { uint weight; bool voted; uint vote; }
struct Proposal { // This is a struct type for a single proposal.
bytes32 name; // short name (up to 32 bytes) of text
uint voteCount; // (=unit256) number of accumulated votes
}
}
```
```javascript
ethers.utils.formatBytes32String('More flowers on the streets')
ethers.utils.parseBytes32String('0x4d616b652062696767657220726f616473000000000000000000000000000000')
```
---
## Contract Template
### `"struct array"` type
```javascript
pragma solidity >=0.4.22 <0.7.0;
contract Ballot {
struct Voter { uint weight; bool voted; uint vote; }
struct Proposal { bytes32 name; uint voteCount; }
address public chairperson;
// Declares state variable to store `Voter` struct for address.
mapping(address => Voter) public voters;
// A dynamically-sized array (="list") of `Proposal` structs.
Proposal[] public proposals;
}
```
---
## Contract Template
### [Reference Types](https://solidity.readthedocs.io/en/latest/types.html#data-location)
* `memory` keyword used for "reference types"
```javascript
pragma solidity >=0.4.22 <0.7.0;
contract Ballot {
struct Voter { uint weight; bool voted; uint vote; }
struct Proposal { bytes32 name; uint voteCount; }
address public chairperson;
mapping(address => Voter) public voters;
Proposal[] public proposals;
// Makes new `Ballot` contract to choose one of `proposalNames`.
constructor (bytes32[] memory proposalNames) public {
// ...
}
}
```
* [click here for more details](https://medium.com/cryptologic/memory-and-storage-in-solidity-4052c788ca86)
---
## Contract Template
### `for loop`, `"struct object"` and `array.push`
```javascript
pragma solidity >=0.4.22 <0.7.0;
contract Ballot {
struct Voter { uint weight; bool voted; uint vote; }
struct Proposal { bytes32 name; uint voteCount; }
address public chairperson;
mapping(address => Voter) public voters;
Proposal[] public proposals;
constructor (bytes32[] memory proposalNames) public {
chairperson = msg.sender; // creator is chairperson
voters[chairperson].weight = 1;
// For each of provided proposal names,
// create new proposal object to add to end of array.
for (uint i = 0; i < proposalNames.length; i++) {
// `Proposal({...})` creates a temporary Proposal object
// and `proposals.push(...)` appends it to end of `proposals`.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
}
```
---
## Contract Template
### [Reference Types](https://solidity.readthedocs.io/en/latest/types.html#data-location)
* `storage` keyword used for "reference types"
* [click here for more details](https://medium.com/cryptologic/memory-and-storage-in-solidity-4052c788ca86)
```javascript
pragma solidity >=0.4.22 <0.7.0;
contract Ballot {
struct Voter { uint weight; bool voted; uint vote; }
struct Proposal { bytes32 name; uint voteCount; }
address public chairperson;
mapping(address => Voter) public voters;
Proposal[] public proposals;
constructor (bytes32[] memory proposalNames) public {
// ...
}
/// Give `voter` the right to vote on this ballot.
// May only be called by `chairperson`.
function giveRightToVote (address voter) public {
require(msg.sender == chairperson, "Only chairperson adds voters.");
require(!voters[voter].voted, "The voter already voted.");
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
/// Give your vote to proposal `proposals[proposal].name`.
function vote (uint proposal) public {
Voter storage sender = voters[msg.sender];
require(sender.weight != 0, "Has no right to vote");
require(!sender.voted, "Already voted.");
sender.voted = true;
sender.vote = proposal;
// If `proposal` is out of the range of the array,
// this will throw automatically and revert all
// changes.
proposals[proposal].voteCount += sender.weight;
}
}
```
---
## Contract Template
### "named returns" and "function re-use"
```javascript
pragma solidity >=0.4.22 <0.7.0;
contract Ballot {
struct Voter { uint weight; bool voted; uint vote; }
struct Proposal { bytes32 name; uint voteCount; }
address public chairperson;
mapping(address => Voter) public voters;
Proposal[] public proposals;
constructor (bytes32[] memory proposalNames) public {
// ...
}
function giveRightToVote (address voter) public {
// ...
}
function vote (uint proposal) public {
// ...
}
/// @dev Computes winning proposal from all previous votes.
/// @return proposal with most votes.
function winningProposal () public view returns (uint winningProposal_) {
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal_ = p;
}
}
// returns `winningProposal_` at the end as the named return value
}
// Calls winningProposal() function to get the index
// of the winner contained in the proposals array and then
/// @return the name of the winning proposal
function winnerName() public view returns (bytes32 winnerName_) {
// re-uses the `winningProposal()` function to calculate result
winnerName_ = proposals[winningProposal()].name;
// returns `winnerName_` at the end as the named return value
}
}
```
---
## Demo Time
copy to open in [play-ed](https://playproject.io/play-ed)
```javascript
ethers.utils.formatBytes32String('More flowers on the streets')
ethers.utils.parseBytes32String('0x4d616b652062696767657220726f616473000000000000000000000000000000')
```
```javascript
pragma solidity >=0.4.22 <0.7.0;
contract Ballot {
struct Voter { uint weight; bool voted; uint vote; }
struct Proposal { bytes32 name; uint voteCount; }
address public chairperson;
mapping(address => Voter) public voters;
Proposal[] public proposals;
constructor (bytes32[] memory proposalNames) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
for (uint i = 0; i < proposalNames.length; i++) {
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
function giveRightToVote (address voter) public {
require(msg.sender == chairperson, "Only chairperson adds voters.");
require(!voters[voter].voted, "The voter already voted.");
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
function vote (uint proposal) public {
Voter storage sender = voters[msg.sender];
require(sender.weight != 0, "Has no right to vote");
require(!sender.voted, "Already voted.");
sender.voted = true;
sender.vote = proposal;
proposals[proposal].voteCount += sender.weight;
}
function winningProposal () public view returns (uint winningProposal_) {
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal_ = p;
}
}
}
function winnerName() public view returns (bytes32 winnerName_) {
winnerName_ = proposals[winningProposal()].name;
}
}
```
---
# Thank you
### questions?
#### connect with us
twitter/telegram
* [@ninabreznik](https://twitter.com/ninabreznik)
* [@serapath](https://twitter.com/serapath)
chat
* [gitter.im/ethereum/play](https://gitter.im/ethereum/play)
{"metaMigratedAt":"2023-06-15T00:47:34.896Z","metaMigratedFrom":"YAML","title":"Solidity","breaks":true,"slideOptions":"{\"theme\":\"white\"}","contributors":"[{\"id\":\"f23eca56-446e-4236-82ac-d8f7524ed36e\",\"add\":93121,\"del\":75877},{\"id\":\"4fa59fe4-4b0e-40a7-beeb-0c8f8c93edbb\",\"add\":878,\"del\":914}]"}