Skip to content

Commit e4ddcf2

Browse files
committed
Update Solidity version, add joint and several promisory note contract.
1 parent 66f0077 commit e4ddcf2

File tree

7 files changed

+302
-4
lines changed

7 files changed

+302
-4
lines changed

coin/Coin.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ contract Coin is ERC20
1414
/**
1515
* Initializes the contract.
1616
*/
17-
constructor() ERC20("WHU", "WHU") public
17+
constructor() ERC20("WHU", "WHU")
1818
{
1919
}
2020
}

liability/Joint.sol

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity >=0.8.0 <0.9.0;
4+
5+
/**
6+
* Promissory note with joint liability.
7+
*/
8+
contract Joint
9+
{
10+
/**
11+
* Outstanding debt for each signatory.
12+
*/
13+
uint256 public debt;
14+
15+
/**
16+
* Signature provided for each signatory.
17+
*/
18+
mapping(address => bool) public signed;
19+
20+
/**
21+
* Promissory note signatories.
22+
*/
23+
address[] public signatories;
24+
25+
/**
26+
* Creates a new contract.
27+
*
28+
* @param signatories_ the promissory note signatories.
29+
*/
30+
constructor(address[] memory signatories_) payable
31+
{
32+
require(msg.value % signatories_.length == 0);
33+
for(uint n = 0; n < signatories_.length; n++)
34+
{
35+
signatories.push(signatories_[n]);
36+
}
37+
}
38+
39+
/**
40+
* Accept payment of the outstanding debt in full from anyone.
41+
*/
42+
function repay() public payable
43+
{
44+
require(debt == msg.value, "only accepts outstanding debt for beneficiary");
45+
debt = 0;
46+
}
47+
48+
/**
49+
* Sign the promisory note.
50+
*/
51+
function sign() public
52+
{
53+
signed[msg.sender] = true;
54+
}
55+
56+
/**
57+
* Withdraw the credited amount.
58+
*/
59+
function withdraw() public
60+
{
61+
bool signatory = false;
62+
for(uint n = 0; n < signatories.length; n++)
63+
{
64+
require(signed[signatories[n]], "all signatories must have signed");
65+
signatory = signatory || signatories[n] == msg.sender;
66+
}
67+
require(signatory, "only a signatory can withdraw the credit");
68+
debt = address(this).balance;
69+
payable(msg.sender).transfer(address(this).balance);
70+
}
71+
}

liability/Several.sol

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity >=0.8.0 <0.9.0;
4+
5+
/**
6+
* Promissory note with several liability.
7+
*/
8+
contract Several
9+
{
10+
/**
11+
* Outstanding debt for each signatory.
12+
*/
13+
mapping(address => uint256) public debt;
14+
15+
/**
16+
* Signature provided for each signatory.
17+
*/
18+
mapping(address => bool) public signed;
19+
20+
/**
21+
* Promissory note signatories.
22+
*/
23+
address[] public signatories;
24+
25+
/**
26+
* Creates a new contract.
27+
*
28+
* @param signatories_ the promissory note signatories.
29+
*/
30+
constructor(address[] memory signatories_) payable
31+
{
32+
require(msg.value % signatories_.length == 0);
33+
for(uint n = 0; n < signatories_.length; n++)
34+
{
35+
signatories.push(signatories_[n]);
36+
}
37+
}
38+
39+
/**
40+
* Accept payment of the proportional outstanding debt for the beneficiary.
41+
*
42+
* @param beneficiary the repayment beneficiary.
43+
*/
44+
function repay(address beneficiary) public payable
45+
{
46+
require(debt[beneficiary] == msg.value, "only accepts outstanding debt for beneficiary");
47+
debt[beneficiary] = 0;
48+
}
49+
50+
/**
51+
* Sign the promisory note.
52+
*/
53+
function sign() public
54+
{
55+
signed[msg.sender] = true;
56+
}
57+
58+
/**
59+
* Withdraw the credited amount.
60+
*/
61+
function withdraw() public
62+
{
63+
bool signatory = false;
64+
for(uint n = 0; n < signatories.length; n++)
65+
{
66+
require(signed[signatories[n]], "all signatories must have signed");
67+
signatory = signatory || signatories[n] == msg.sender;
68+
}
69+
require(signatory, "only a signatory can withdraw the credit");
70+
uint256 proportion = address(this).balance / signatories.length;
71+
for(uint n = 0; n < signatories.length; n++)
72+
{
73+
debt[signatories[n]] = proportion;
74+
}
75+
payable(msg.sender).transfer(address(this).balance);
76+
}
77+
}

liability/Several_test.sol

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity >=0.8.0 <0.9.0;
4+
5+
import "hardhat/console.sol";
6+
import "remix_accounts.sol";
7+
import "remix_tests.sol";
8+
import "./Several.sol";
9+
10+
contract SeveralTest is Several
11+
{
12+
address creditor;
13+
address signatoryA;
14+
address signatoryB;
15+
16+
function beforeAll () public
17+
{
18+
creditor = TestsAccounts.getAccount(0);
19+
signatoryA = TestsAccounts.getAccount(1);
20+
signatoryB = TestsAccounts.getAccount(2);
21+
}
22+
23+
/// #sender: account-0
24+
constructor(address creditor_) payable Several(testSignatories())
25+
{
26+
require(msg.sender == creditor_, "should have correct sender");
27+
Assert.equal(msg.value, 51 ether, "should have correct value");
28+
}
29+
30+
function testSignatories() internal pure returns (address[] memory)
31+
{
32+
address[] memory signatories = new address[](2);
33+
signatories[0] = TestsAccounts.getAccount(1);
34+
signatories[1] = TestsAccounts.getAccount(2);
35+
return signatories;
36+
}
37+
38+
/// #sender: account-1
39+
function testSignA() public
40+
{
41+
Assert.equal(msg.sender, signatoryA, "should have correct sender");
42+
sign();
43+
}
44+
45+
/// #sender: account-2
46+
function testSignB() public payable
47+
{
48+
Assert.equal(msg.sender, signatoryB, "should have correct sender");
49+
sign();
50+
}
51+
52+
/// #sender: account-1
53+
function testWithdraw() public payable
54+
{
55+
Assert.equal(msg.sender, signatoryA, "should have correct sender");
56+
uint256 initial = address(msg.sender).balance;
57+
withdraw();
58+
Assert.equal(address(signatoryA).balance, initial + 0 ether, "should be credited");
59+
}
60+
61+
/// #sender: account-1
62+
/// #value: 0
63+
function testRepay() public payable
64+
{
65+
Assert.equal(msg.sender, signatoryA, "should have correct sender");
66+
Assert.equal(msg.value, 0 ether, "should send 1 ether");
67+
repay(signatoryA);
68+
}
69+
}

piggybank/Piggybank.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ contract Piggybank
2323
/**
2424
* Accept payments.
2525
*/
26-
function pay() external payable
26+
receive() external payable
2727
{
2828
}
2929

piggybank/Piggybank_test.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ contract PiggybankTest is Piggybank
3333
{
3434
Assert.equal(msg.sender, grandmom, "should have correct sender");
3535
Assert.equal(msg.value, 5e18, "should have correct value");
36-
address(piggybank).transfer(msg.value);
36+
payable(address(piggybank)).transfer(msg.value);
3737
Assert.equal(address(piggybank).balance, msg.value, "should have some savings");
3838
}
3939

@@ -43,7 +43,7 @@ contract PiggybankTest is Piggybank
4343
{
4444
Assert.equal(msg.sender, grandpop, "should have correct sender");
4545
Assert.equal(msg.value, 5e18, "should have correct value");
46-
address(piggybank).transfer(msg.value);
46+
payable(address(piggybank)).transfer(msg.value);
4747
Assert.equal(address(piggybank).balance, msg.value * 2, "should have more savings");
4848
}
4949

web3-erc20/index.html

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>ERC-20 Demo App</title>
7+
<link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.9.0/semantic.min.css" rel="stylesheet"/>
8+
<script crossorigin="anonymous" src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.8.1/web3.min.js"></script>
9+
<script crossorigin="anonymous" src="https://cdnjs.cloudflare.com/ajax/libs/ethers/6.8.1/ethers.umd.min.js"></script>
10+
</head>
11+
<body>
12+
<div class="ui container">
13+
<h1>ERC-20 Demo</h1>
14+
<h4 class="ui dividing header">Read blockchain</h4>
15+
<form class="ui form">
16+
<div class="field">
17+
<div class="two fields">
18+
<div class="field">
19+
<button class="ui blue button" id="getBlockNumber" type="button">
20+
<i class="icon"></i>
21+
Get latest block number
22+
</button>
23+
</div>
24+
<div class="field">
25+
<div class="ui blue label">
26+
<i class="cube icon"></i>
27+
<a class="detail" id="blockNumber" target="_blank"></a>
28+
</div>
29+
</div>
30+
</div>
31+
</div>
32+
</form>
33+
<br/>
34+
<br/>
35+
<h4 class="ui dividing header">System log</h4>
36+
<pre style="color:#888"></pre>
37+
<br/>
38+
</div>
39+
<script type="module">
40+
const node = "https://eth-mainnet.gateway.pokt.network/v1/lb/29934f7f10137fb45e8609a0";
41+
const provider = new ethers.JsonRpcProvider(node);
42+
43+
document.querySelector("#getBlockNumber").addEventListener("click", async () =>
44+
{
45+
document.querySelector("#getBlockNumber i").classList.add("loading", "spinner");
46+
try
47+
{
48+
const blockNumber = await provider.getBlockNumber();
49+
document.querySelector("pre").textContent += `Ethereum blockchain at block number ${blockNumber}.\n`;
50+
document.querySelector("#blockNumber").href = `https://etherscan.io/block/${blockNumber}`;
51+
document.querySelector("#blockNumber").textContent = `Block number ${blockNumber}`;
52+
}
53+
finally
54+
{
55+
document.querySelector("#getBlockNumber i").classList.remove("loading", "spinner");
56+
}
57+
58+
const abi =
59+
[
60+
"function balanceOf(address a) view returns (uint)",
61+
"function decimals() view returns (uint8)",
62+
"function symbol() view returns (string)",
63+
"function transfer(address to, uint amount)"
64+
];
65+
const contract = new ethers.Contract("0xdac17f958d2ee523a2206206994597c13d831ec7", abi, provider)
66+
const symbol = await contract.symbol();
67+
const decimals = await contract.decimals();
68+
const balance = await contract.balanceOf("ethers.eth");
69+
console.log(decimals, symbol);
70+
71+
const wallet = new ethers.BrowserProvider(window.ethereum);
72+
await wallet.send('eth_requestAccounts', []);
73+
const signer = await wallet.getSigner();
74+
const tx = await signer.sendTransaction({to: "ethers.eth", value: ethers.parseEther("1.0")});
75+
/*const amount = ethers.parseUnits("1.0", 18);
76+
const tx = await contract.transfer("ethers.eth", amount, signer);
77+
await tx.wait()*/
78+
});
79+
</script>
80+
</body>
81+
</html>

0 commit comments

Comments
 (0)