Hack. Eat. Sleep. Repeat!!!
sudo npm install --global solc
//version
pragma solidity 0.8.30; //use only 0.8.30
//use versions between 0.8.19 and 0.9.0 (excluded)
pragma solidity ^0.8.19;
pragma solidity >=0.8.19 <0.9.0;
//SPDX-License-Identifier: MIT
//solidity version
pragma solidity ^0.8.30;
solcjs-:solcjs --bin main.sol
//SPDX-License-Identifier: MIT
//solidity version
pragma solidity ^0.8.30;
contract simpleStorage {
//code goes thus
}
bool hasFavoriteNumber = true; //true or false
bool hasFavoriteNumber = true;
uint256 favoriteNumber = 88;
string favoriteNumberInText = "eighty-eight";
int256 favoriteInt = -88;
address myAddress = 0xAB1b7206aa6840C795aB7A6AE8b15417B7E63A8D;
bytes32 favoriteBytes32 = "cat";
function-://SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
contract Storage{
uint256 digit = 100;
function store(uint256 _digit) public {
digit = _digit;
}
}
uint256 public digit = 1000;
public
private
internal
external
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
contract Storage{
uint256 digit = 100;
function store(uint256 _digit) public {
digit = _digit;
}
//view
function retrieve() public view returns {
return digit;
}
//pure
function retrieve() public pure returns {
return 7;
}
}
memory -:function createZombie(string memory _name,uint _dna) public {
}
return, specify like thisstring greeting = "What's up dog";
function sayHello() public returns (string memory) {
return greeting;
}
viewfunction sayHello() public view returns (string memory){
}
function _multiplyNumbers(uint a, uint b) private pure returns (uint memory) {
return a * b;
}
uint256 numbers-:uint256[] digits = [0,10,90];
struct Person {
string name;
uint256 age;
}
Person public ade = Person("Ade",100);
Person[] public people;
Person[3] public three_people;
array of structs with a function.//function push to three_people array
function push_value(uint256 _negativeNumber, string memory _name) public{
people.push(Person(_negativeNumber,_name));
}
Calldata
Memory
Storage
Stack
Code
Logs
Calldata and memory are temporary storage locations during function execution.calldata is read-only, used for function inputs that can’t be modified. In contrast, memory allows for read-write access, letting variables be changed within the function. To modify calldata variables, they must first be loaded into memory.string memory name = "Ade";
keccak256 is the version of SHA3.It maps an input into a 256-bit hexadecimal number.It expects a parameter of type bytes.It means we have to pack string to bytes.keccak256(abi.encodePacked("deadbeef"))
uint a = 6;
uint8 b = 9;
uint8 c = b * uint8(a);
// declare the event
event IntegersAdded(uint x, uint y, uint result);
function add(uint _x, uint _y) public returns (uint) {
uint result = _x + _y;
// fire an event to let the app know the function was called:
emit IntegersAdded(_x, _y, result);
return result;
}
YourContract.IntegersAdded(function(error, result) {
// do something with the result
})
pragma solidity >=0.5.0 <0.6.0;
contract ZombieFactory {
event NewZombie(uint zombieId,string name,uint dna);
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
function _createZombie(string memory _name, uint _dna) private {
uint id = zombies.push(Zombie(_name, _dna)) - 1; // 2. Store the result of `zombies.push(...) - 1` in a `uint` called `id`
emit NewZombie(id, _name, _dna);
}
function _generateRandomDna(string memory _str) private view returns (uint) {
uint rand = uint(keccak256(abi.encodePacked(_str)));
return rand % dnaModulus;
}
function createRandomZombie(string memory _name) public {
uint randDna = _generateRandomDna(_name);
_createZombie(_name, randDna);
}
}
mapping and addressaddress which you can think of as a bank account which looks like this 0x0cE446255506E92DF41614C46F1d6df9Cc969183. Mappings are another way of storing datamapping (address => uint) public accountBalance;
mapping (uint => string ) userIdToName;
msg.sender which belongs to the address of the person that called a function in a contract.Note: In Solidity, function execution always needs to start with an external caller. A contract will just sit on the blockchain doing nothing until someone calls one of its functions. So there will always be a msg.sender.
mapping (address => uint ) public contractAddresses;
function setAddressValue(uint memory _number) public {
contractAddresses[msg.sender] = _number;
}
uint number = 0;
number++;
Require is used to ensure a line of code throws an error if the condition is not fulfilled.require(abi.encodePacked('a') == abi.encodePacked('b'));
contract Doge {
}
//is extends a subclass to base class
contract baseDoge is Doge {
}
import "./someContract.sol"
contract Doge is someContract {
}
Storage v Memory data location-:Storage data are stored on the blockchain while Memory values are stored in the RAM or the hard-disk.storage because state variables are stored in it by default and permanently written to the blockchain, while variables stored in function are stored in the memory and disappears after a function gets called.function feedAndMultiply(uint _zombieId, uint _targetDna) public {
require(msg.sender == zombieToOwner[_zombieId]);
Zombie storage myZombie = zombies[_zombieId];
// start here
}
struct.key.e.gmyZombie.dna
internal and external.internal is like private but it is accessible by a contract that inherits the contract.external is similar to public, except that these functions can ONLY be called outside the contract — they can’t be called by other functions inside that contract.interface.interface is declared like this without the curly braces-:contract KittyInterface {
function getKitty(uint256 _id) external view returns (
bool isGestating,
bool isReady,
uint256 cooldownIndex,
uint256 nextActionAt,
uint256 siringWithId,
uint256 birthTime,
uint256 matronId,
uint256 sireId,
uint256 generation,
uint256 genes
);
}
address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
// Initialize kittyContract here using `ckAddress` from above
KittyInterface kittyContract = KittyInterface(ckAddress);
function processMultipleReturns() external { uint a; uint b; uint c; // This is how you do multiple assignment: (a, b, c) = multipleReturns(); }
// Or if we only cared about one of the values: function getLastReturnValue() external { uint c; // We can just leave the other fields blank: (,,c) = multipleReturns(); }
- `if` statements-:
```solidity
if () {
}
constructor() is a constructor, which is an optional special function. It will get executed only one time, when the contract is first created.
Function Modifiers: modifier onlyOwner(). Modifiers are kind of half-functions that are used to modify other functions, usually to check some requirements prior to executionmodifier onlyOwner() {
require(isOwner());
_;
}
function tryModifier(uint256 _number) external onlyOwner {
}
The variable
nowwill return the current Unix timestamp.Solidity also contains the time unitsseconds,minutes,hours,days,weeksandyears. These will convert to a uint of the number of seconds in that length of time. Note: The uint32(…) is necessary because now returns a uint256 by default. So we need to explicitly convert it to a uint32.
function _doStuff(Zombie storage _zombie) internal {
// do stuff with _zombie
}
pragma solidity >=0.5.0 <0.6.0;
import "./zombiefactory.sol";
contract KittyInterface {
function getKitty(uint256 _id) external view returns (
bool isGestating,
bool isReady,
uint256 cooldownIndex,
uint256 nextActionAt,
uint256 siringWithId,
uint256 birthTime,
uint256 matronId,
uint256 sireId,
uint256 generation,
uint256 genes
);
}
contract ZombieFeeding is ZombieFactory {
KittyInterface kittyContract;
function setKittyContractAddress(address _address) external onlyOwner {
kittyContract = KittyInterface(_address);
}
// 1. Define `_triggerCooldown` function here
function _triggerCooldown(Zombie storage _zombie) internal {
_zombie.readyTime = uint32(now + cooldownTime);
}
// 2. Define `_isReady` function here
function _isReady(Zombie storage _zombie) internal view returns (bool){
return (_zombie.readyTime <= now );
}
function feedAndMultiply(uint _zombieId, uint _targetDna, string memory _species) public {
require(msg.sender == zombieToOwner[_zombieId]);
Zombie storage myZombie = zombies[_zombieId];
_targetDna = _targetDna % dnaModulus;
uint newDna = (myZombie.dna + _targetDna) / 2;
if (keccak256(abi.encodePacked(_species)) == keccak256(abi.encodePacked("kitty"))) {
newDna = newDna - newDna % 100 + 99;
}
_createZombie("NoName", newDna);
}
function feedOnKitty(uint _zombieId, uint _kittyId) public {
uint kittyDna;
(,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
feedAndMultiply(_zombieId, kittyDna, "kitty");
}
}
An important security practice is to examine all your public and external functions, and try to think of ways users might abuse them. Remember — unless these functions have a modifier like onlyOwner, any user can call them and pass them any data they want to.
Function modifiers-: They can also take arguments.
modifier aboveLevel(uint _level, uint _zombieId) {
require(zombies[_zombieId].level >= _level);
_;
}
Note: calldata is somehow similar to memory, but it’s only available to external functions.
viewfunctions don’t cost any gas when they’re called externally by a user.This is because view functions don’t actually change anything on the blockchain – they only read the data. So marking a function with view tells web3.js that it only needs to query your local Ethereum node to run the function, and it doesn’t actually have to create a transaction on the blockchain (which would need to be run on every single node, and cost gas).
uint[] memory result = new uint[](ownerZombieCount[_owner]);
// Start here
return result;
for (uint i = 0; i < zombies.length; i++) {
if (zombieToOwner[i] == _owner) {
result[counter] = i;
counter++;
}
}
When you call an API function on a normal web server, you can’t send US dollars along with your function call — nor can you send Bitcoin.But in Ethereum, because the money (Ether), the data (transaction payload), and the contract code itself all live on Ethereum, it’s possible for you to call a function and pay money to the contract at the same time.
function levelUp(uint _zombieId) external payable {
require(msg.value == levelUpFee);
zombies[_zombieId].level++;
}
It is important to note that you cannot transfer Ether to an address unless that address is of type address payable. But the _owner variable is of type uint160, meaning that we must explicitly cast it to address payable. Once you cast the address from uint160 to address payable, you can transfer Ether to that address using the transfer function, and address(this).balance will return the total balance stored on the contract. So if 100 users had paid 1 Ether to our contract, address(this).balance would equal 100 Ether. You can use transfer to send funds to any Ethereum address. For example, you could have a function that transfers Ether back to the msg.sender if they overpaid for an item:
uint itemFee = 0.001 ether; msg.sender.transfer(msg.value - itemFee);
function withdraw() external onlyOwner {
address payable _owner = address(uint160(owner()));
_owner.transfer(address(this).balance);
}
keccak256 hash function. uint randNonce = 0;
function randMod(uint _modulus) internal returns (uint) {
randNonce++;
return uint(keccak256(abi.encodedPacked(now,msg.sender,randNonce))) % _modulus;
}
function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) ownerOf(_zombieId) {
zombies[_zombieId].dna = _newDna;
}
transferFrom(address _from, address _to, uint256 _amount) and balanceOf(address _owner)
mapping( address => uint256) balances, that keeps track of balances for each address. So basically a token is just a contract that keeps track of who owns how much of that token, and some functions so those users can transfer their tokens to other addresses.contract ERC721 {
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
}
contract Sathoshi is Sensei,Blackie {
}
function transferFrom(address _from, address _to, uint256 _tokenId) external payable; and function approve(address _approved, uint256 _tokenId) external payable; function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
import "./safemath.sol"
contract ZombieFactory is Ownable {
// 2. Declare using safemath here
using SafeMath for uint256;