Taesoo Kim
Taesoo Kim & Ammar Askar
Time to finalize teammates for Part 2.
There is a team-finding thread available on Ed-Discussions, please use it and utilize the time after class today.
Spreadsheet linked on Ed-Discussions must be filled out by everyone by next class (17th February).
struct S {
uint128 a;
uint128 b;
uint[2] staticArray;
uint[] dynArray;
}
// Storage (global) variables.
address public owner;
bool public completed1;
bool public completed2;
mapping(bool => mapping(uint128 => mapping(string => S))) data;
// Find the slot.
data[false][0xdeadc0de]["world!"].staticArray[1] = 0xdecafbad;
As a reminder, slot usage for mappings:
map[key] = value
is stored at
keccak256(key . #slot)
address public owner;
bool public completed1;
bool public completed2;
mapping(bool => mapping(uint128 => mapping(string => S))) data;
Address is 20 bytes, bools are 1 byte. So owner
,
completed1
and completed2
all stored in slot
0.
map[key] = value
is stored at
keccak256(key . #slot)
# Given based on where data is.
>>> s1 = 1
# Next let's resolve data[false], key = false = 0.
>>> s2 = web3.solidityKeccak(['uint256', 'uint256'], [0, s1])
# Now key = 0xdeadc0de
>>> s3 = web3.solidityKeccak(['uint256', 'uint256'], [0xdeadc0de, s2.int()])
# Now key = "world!"
>>> s4 = web3.solidityKeccak(['string', 'uint256'], ["world!", s3.int()])
>>> web3.eth.getStorageAt(lab4.address, s4.int() + 2)
'0x00000000000000000000000000000000000000000000000000000000decafbad'
Let’s try sending it some balance!
>>> accounts[2].transfer(force.address, amount='1 gwei')
Transaction sent: 0x2b2ce04f62ca6da23be7a88e572cacd13cef52e32f9c62ffe8513162d29e19f7
Max fee: 2.000000014 gwei Priority fee: 2.0 gwei
Gas limit: 30000000 Nonce: 271
Transaction confirmed (reverted)
Reverted, there are no payable methods :(
>>> s = SelfDestructor.deploy({'value': '1 gwei'})
...
SelfDestructor deployed at: 0x4BEDC96985b51E4b63b124b75541A6e671ff7634
>>> s.exploit(force.address)
...
SelfDestructor.exploit confirmed Block: 258896
>>> force.balance()
1000000000
selfdestruct
can force your contract to receive eth,
make sure you are aware this.balance
can be changed in
this way!
The most common high-level contract you will see involves tokens.
Just like Ethereum itself, they represent a fungible asset.
Fungible: 1 gwei is the same as any other 1 gwei.
Tokens are used for a wide variety of applications:
Most Tokens implement a set of common APIs as part of an
interface
. This interface is called
ERC-20.
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public
returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view
returns (uint256 remaining)
Ref. ERC-20
Returns the name of the token. e.g. "CatToken"
Returns a symbol representing the token.
e.g. "CAT"
The number of decimal places to use for the currency. For example
you can store $2.52 as 252 and use decimals() = 2
.
The total number of tokens in circulation.
Gets the token balance of a particular address.
Transfers tokens from the sender’s address to the to
address.
function approve(address _spender, uint256 _value) public
returns (bool success)
function allowance(address _owner, address _spender) public view
returns (uint256 remaining)
Approves spender
to spend value
tokens on
your behalf.
Transfers value
tokens from someone else’s
token balance if they approved it.
Gives a universal set of interfaces you can use to accept any sort of token in your own contract.
Here’s a contract that you can sell any sort of token to, and it will buy it at a rate of 1gwei per token.
Integrates with block explorers.
and integrates with wallets.
Hold tokens for the user until voting is finished.
IERC20 votingToken = IERC20(...);
function vote(uint proposal) public {
uint256 balance = votingToken.balanceOf(msg.sender);
require(balance > 0, "Need at least 1 token to vote");
require(
classToken.transferFrom(msg.sender, address(this), balance),
"Failed to transfer tokens to voting contract");
sender.heldAmount = balance;
proposals[proposal].voteCount += balance;
}
VoteForSnacks
contract available at:
0x76c30713dfC8b0763Ae6577465568bA75B8c71cC
Make sure to withdraw your ClassToken once the voting period is over.
ERC-721 is for NFTs (Non-Fungible Tokens). In this instance, one token is not the same as any other token.
Each token carries a tokenId
to uniquely identify
it.
CryptoKitties#178021, tokenURI
points to: