Created by M. Massenzio, 2022-04-15
A Smart Contract
is a program that runs on the ETH B/c, a collection of code/data that resides at a specific address; it is a type of Account
, so it can send transactions over the network and has a balance.
An account
is an entity with an ETH balance: it can
- receive,
- hold, and
- send
ETH and Tokens
.
Transactions from an external account to a contract account can trigger code which can execute many actions, such as transferring tokens or even creating a new contract
Contract accounts have a 42 hex address (168 bits): it gets generated from the creator's address and their nonce
.
Accounts have four fields:
nonce
balance
codeHash
storageRoot
(or 'storage hash')
An Account
is protected by a Private Key
which is made up of 64 hex characters (256 bits) and can be encrypted with a password.
Public Key
is generated with an EC signature algorithm (Keccak-256), last 20 bytes.
One wei
is 10-18 ether
; one gwei
is 109 wei
and there are 109 gwei
in 1 ether
.
At current prices (4/24/2022) 1 ETH ~ 2,854 USD, so 1 USD ~ 350k gwei
With gas
price hovering around 15-20 gwei
this week, and a transaction costing 21,000 gas
, sending a contract to the ETH blockchain costs around:
21,000 gas x 20 gwei / 350,00 = $1.20
plus the cost of the contract execution.
Setting up the dev env with REMIX and creating the first token: see the Token.sol source.
contract MarcoToken is ERC20Capped, Ownable {
// Specify the decimals: one Marco Token can be subdivided in 10^6
// (one million) Willies.
uint TOKEN = 10**6;
constructor(uint256 cap) ERC20("MarcoToken", "MRCT")
ERC20Capped(cap) {
}
function issueTokens(uint tokens) public onlyOwner {
_mint(msg.sender, tokens * TOKEN);
}
}
For local development we use Hardhat:
- installed the latest Node.js LTS via
nvm
└─( nvm install 16.14.2
└─( node --version
v16.14.2
- Install Hardhat
└─( npm init
└─( npm install --save-dev hardhat
- Initialize project with Hardhat
└─( npx hardhat
TODO
Audit finds many vulnerabilities, some
high
: fix them
- Install Ganache
For local development, we use Ganache installed locally.
Download the Linux AppInit file, chmod +x
it and then execute it.
This will run a server on http://127.0.0.1:8545
which will need to be configured in the API_URL
(see the ganache.env
configuration).
Created an account with Alchemy and created my first app (MarcoToken
), and configured to use the Mumbai Polygon network.
The API App key and the Metamask Wallet account have been saved in the .env
file (added to .gitignore
):
npm install dotenv
touch .env
echo ".env" >> .gitignore
vim .env
Polygon can be used to issue test tokens (MATIC
) to use to deploy the MarcoToken
(use your Wallet address, from Metamask).
Remember to enable test networks and to add Polygon Mumbai to the Metamask extension (using Chainlist).
Added support for OpenZeppelin:
npm install @openzeppelin/contracts
and added Token.sol
to be deployed via deploy.js
.
Hardhat provides some basic functionality:
Used npx hardhat compile
to compile my contracts
to artifacts
(these will be needed by Web3Py
to extract the ABI
and execute RPC calls against the contract).
Deploy with Hardhat using the deploy.js
script
└─( npx hardhat run ./scripts/deploy.js --network mumbai
Token deployed to: 0x3ec2C1426A615F3bD59Ca31203657bc9E2e53d18
or locally to the Ganache blockchain:
└─( npx hardhat --network localhost run scripts/deploy.js
Contract deployed to: 0x308Bd7f1518E68cF1811ad00e4bbF185dDcca43c
The deployment of the Contract can be seen in the TESTNET Polygon Explorer: use the address emitted by the script to confirm the transaction was successfully processed.
The token can then be added to Metamask walled, using the Import Token
functionality and the contract's address, as emitted by the deploy.js
script:
When running the issue.js
script, we need a Provider
(see ethers
API Providers); if the name of the provider is not one recognized, it will emit a cryptic error:
TypeError: Cannot read properties of null (reading 'name')
See the AlchemyProvider
doc page for a list of allowed providers (we use maticmum
for the Polygon Matic Mumbai testnet).
This is defined in the Future.sol
Solidity code, and allows a buyer
and seller
to agree to exchange a security by a given time, or the contract will expire.
The owner
of the contract (the address that deploys it) will collect a fee of 0.05 ETH
from the seller
when they pay()
for the contract: until the Future is paid, it cannot be settled - the buyer
will then settle()
the contract for the agreed-upon value
, before the future expires (expires_at
timestamp).
This repository is configured to run tests against the newly crafted Solidity code via a number of Python tests which interact with the Contract itself.
To test any changes to the .sol
file have been successful use:
python -m unittest discover -s tests