Blockchain Technology: Solidity Tutorials -Part-III.
This is continuation of the blogs
Special Variables and Functions
There are special variables and functions which always exist in the global namespace.
Block and Transaction Properties
block.coinbase
(address
): current block miner's addressblock.difficulty
(uint
): current block difficultyblock.gaslimit
(uint
): current block gaslimitblock.number
(uint
): current block numberblock.blockhash
(function(uint) returns (bytes32)
): hash of the given blockblock.timestamp
(uint
): current block timestampmsg.data
(bytes
): complete calldatamsg.gas
(uint
): remaining gasmsg.sender
(address
): sender of the message (current call)msg.value
(uint
): number of wei sent with the messagenow
(uint
): current block timestamp (alias forblock.timestamp
)tx.gasprice
(uint
): gas price of the transactiontx.origin
(address
): sender of the transaction (full call chain)
Cryptographic Functions
sha3(...) returns (bytes32)
: compute the SHA3 hash of the (tightly packed) argumentssha256(...) returns (bytes32)
: compute the SHA256 hash of the (tightly packed) argumentsripemd160(...) returns (bytes20)
: compute RIPEMD of 256 the (tightly packed) argumentsecrecover(bytes32, byte, bytes32, bytes32) returns (address)
: recover public key from elliptic curve signature
In the above, "tightly packed" means that the arguments are concatenated without padding, i.e.
sha3("ab", "c") == sha3("abc") == sha3(0x616263) == sha3(6382179) = sha3(97, 98, 99)
. If padding is needed, explicit type conversions can be used.Contract Related
this
(current contract's type): the current contract, explicitly convertible toaddress
suicide(address)
: suicide the current contract, sending its funds to the given address
Furthermore, all functions of the current contract are callable directly including the current function.
Functions on addresses
It is possible to query the balance of an address using the property
balance
and to send Ether (in units of wei) to an address using the send
function:address x = 0x123;
if (x.balance < 10 && address(this).balance >= 10) x.send(10);
Furthermore, to interface with contracts that do not adhere to the ABI (like the classic NameReg contract), the function
call
is provided which takes an arbitrary number of arguments of any type. These arguments are ABI-serialized (i.e. also padded to 32 bytes). One exception is the case where the first argument is encoded to exactly four bytes. In this case, it is not padded to allow the use of function signatures here.address nameReg = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2;
nameReg.call("register", "MyName");
nameReg.call(bytes4(sha3("fun(uint256)")), a);
Note that contracts inherit all members of address, so it is possible to query the balance of the current contract using
this.balance
.Order of Evaluation of Expressions
The evaluation order of expressions is not specified (more formally, the order in which the children of one node in the expression tree are evaluated is not specified, but they are of course evaluated before the node itself). It is only guaranteed that statements are executed in order and short-circuiting for boolean expressions is done.
Arrays
Both variably and fixed size arrays are supported in storage and as parameters of external functions:
contract ArrayContract {
uint[2**20] m_aLotOfIntegers;
bool[2][] m_pairsOfFlags;
function setAllFlagPairs(bool[2][] newPairs) {
// assignment to array replaces the complete array
m_pairsOfFlags = newPairs;
}
function setFlagPair(uint index, bool flagA, bool flagB) {
// access to a non-existing index will stop execution
m_pairsOfFlags[index][0] = flagA;
m_pairsOfFlags[index][1] = flagB;
}
function changeFlagArraySize(uint newSize) {
// if the new size is smaller, removed array elements will be cleared
m_pairsOfFlags.length = newSize;
}
function clear() {
// these clear the arrays completely
delete m_pairsOfFlags;
delete m_aLotOfIntegers;
// identical effect here
m_pairsOfFlags.length = 0;
}
bytes m_byteData;
function byteArrays(bytes data) external {
// byte arrays ("bytes") are different as they are stored without padding,
// but can be treated identical to "uint8[]"
m_byteData = data;
m_byteData.length += 7;
m_byteData[3] = 8;
delete m_byteData[2];
}
}
Structs
Solidity provides a way to define new types in the form of structs, which is shown in the following example:
contract CrowdFunding {
struct Funder {
address addr;
uint amount;
}
struct Campaign {
address beneficiary;
uint fundingGoal;
uint numFunders;
uint amount;
mapping (uint => Funder) funders;
}
uint numCampaigns;
mapping (uint => Campaign) campaigns;
function newCampaign(address beneficiary, uint goal) returns (uint campaignID) {
campaignID = numCampaigns++; // campaignID is return variable
Campaign c = campaigns[campaignID]; // assigns reference
c.beneficiary = beneficiary;
c.fundingGoal = goal;
}
function contribute(uint campaignID) {
Campaign c = campaigns[campaignID];
Funder f = c.funders[c.numFunders++];
f.addr = msg.sender;
f.amount = msg.value;
c.amount += f.amount;
}
function checkGoalReached(uint campaignID) returns (bool reached) {
Campaign c = campaigns[campaignID];
if (c.amount < c.fundingGoal)
return false;
c.beneficiary.send(c.amount);
c.amount = 0;
return true;
}
}
The contract does not provide the full functionality of a crowdfunding contract, but it contains the basic concepts necessary to understand structs. Struct types can be used as value types for mappings and they can itself contain mappings (even the struct itself can be the value type of the mapping, although it is not possible to include a struct as is inside of itself). Note how in all the functions, a struct type is assigned to a local variable. This does not copy the struct but only store a reference so that assignments to members of the local variable actually write to the state.
Enums
Enums are another way to create a user-defined type in Solidity. They are explicitly convertible to and from all integer types but implicit conversion is not allowed. The variable of enum type can be declared as constant.
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
ActionChoices choices;
ActionChoices constant defaultChoice = ActionChoices.GoStraight;
function setGoStraight()
{
choices = ActionChoices.GoStraight;
}
function getChoice() returns (uint)
{
return uint(choices);
}
function getDefaultChoice() returns (uint)
{
return uint(defaultChoice);
}
}
Post a Comment