0xfacet-contracts 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/Manifest.txt +15 -0
- data/README.md +24 -0
- data/Rakefile +32 -0
- data/lib/0xfacet/contracts/ERC20.rb +76 -0
- data/lib/0xfacet/contracts/ERC721.rb +103 -0
- data/lib/0xfacet/contracts/EtherBridge.rb +115 -0
- data/lib/0xfacet/contracts/EtherBridgeV2.rb +100 -0
- data/lib/0xfacet/contracts/EthscriptionERC20Bridge.rb +89 -0
- data/lib/0xfacet/contracts/GenerativeERC721.rb +95 -0
- data/lib/0xfacet/contracts/OpenEditionERC721.rb +56 -0
- data/lib/0xfacet/contracts/PublicMintERC20.rb +38 -0
- data/lib/0xfacet/contracts/UnsafeNoApprovalERC20.rb +39 -0
- data/lib/0xfacet/contracts/Upgradeable.rb +37 -0
- data/lib/0xfacet/contracts.rb +8 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9fac7c3c3df979bc789b4b300cf331972a368edb51fd2c8646654564ecd25e81
|
4
|
+
data.tar.gz: 696b46279ae0a4b54c26249ae879c4514f80e0720aaeada490874d90bacb7d53
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 580db8d5ab28967cc8b3886de2f2bedc53efe5ba83b6c87d2786c08c3e4e716223fc570b9eb84a4f7b346755a67a9552e87f6bbf22da7296028c20f67e7c2659
|
7
|
+
data.tar.gz: 6e2f3120f2978f4b9e29c1e80f17bff93380400d956c9b436679ee0abd4a90f9992bdd7e63d97ebecf3d85ea975a7d7a7bcd0b062ab78fdfe0afe47d6eccd415
|
data/CHANGELOG.md
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
CHANGELOG.md
|
2
|
+
Manifest.txt
|
3
|
+
README.md
|
4
|
+
Rakefile
|
5
|
+
lib/0xfacet/contracts.rb
|
6
|
+
lib/0xfacet/contracts/ERC20.rb
|
7
|
+
lib/0xfacet/contracts/ERC721.rb
|
8
|
+
lib/0xfacet/contracts/EtherBridge.rb
|
9
|
+
lib/0xfacet/contracts/EtherBridgeV2.rb
|
10
|
+
lib/0xfacet/contracts/EthscriptionERC20Bridge.rb
|
11
|
+
lib/0xfacet/contracts/GenerativeERC721.rb
|
12
|
+
lib/0xfacet/contracts/OpenEditionERC721.rb
|
13
|
+
lib/0xfacet/contracts/PublicMintERC20.rb
|
14
|
+
lib/0xfacet/contracts/UnsafeNoApprovalERC20.rb
|
15
|
+
lib/0xfacet/contracts/Upgradeable.rb
|
data/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# 0xFacet Rubidity O.G. Standard Contracts
|
2
|
+
|
3
|
+
0xfacet-contracts - rubidity o.g. standard contracts (incl. ERC20, PublicMintERC20, ERC721, GenerativeERC721, etc.)
|
4
|
+
|
5
|
+
* home :: [github.com/s6ruby/rubidity.review](https://github.com/s6ruby/rubidity.review)
|
6
|
+
* bugs :: [github.com/s6ruby/rubidity.review/issues](https://github.com/s6ruby/rubidity/issues)
|
7
|
+
* gem :: [rubygems.org/gems/0xfacet-contracts](https://rubygems.org/gems/0xfacet-contracts)
|
8
|
+
* rdoc :: [rubydoc.info/gems/0xfacet-contracts](http://rubydoc.info/gems/0xfacet-contracts)
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
## About
|
13
|
+
|
14
|
+
What's happening herè?
|
15
|
+
|
16
|
+
The idea is to look at the facet vm code as-is (that is, NOT suggesting new or alternate syntax and semantics) in the review / commentary
|
17
|
+
and start to (re)package / modular-ize
|
18
|
+
code in "place holder" gems (waiting for adoption by the founders) such as 0xfacet and 0xfacet-typed and 0xfacet-rubidity.
|
19
|
+
|
20
|
+
See [Rubidity O.G. (Dumb Contracts) Public Code Review / (More) Tests / Gems & More »](https://github.com/s6ruby/rubidity.review)
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'hoe'
|
2
|
+
|
3
|
+
# require './lib/0xfacet/version.rb'
|
4
|
+
|
5
|
+
|
6
|
+
Hoe.spec '0xfacet-contracts' do
|
7
|
+
|
8
|
+
self.version = '0.0.1'
|
9
|
+
|
10
|
+
self.summary = '0xfacet-contracts - rubidity o.g. standard contracts (incl. ERC20, PublicMintERC20, ERC721, GenerativeERC721, etc.)'
|
11
|
+
self.description = summary
|
12
|
+
|
13
|
+
self.urls = { home: 'https://github.com/s6ruby/rubidity.review' }
|
14
|
+
|
15
|
+
self.author = 'Gerald Bauer'
|
16
|
+
self.email = 'gerald.bauer@gmail.com'
|
17
|
+
|
18
|
+
# switch extension to .markdown for gihub formatting
|
19
|
+
self.readme_file = 'README.md'
|
20
|
+
self.history_file = 'CHANGELOG.md'
|
21
|
+
|
22
|
+
self.extra_deps = [
|
23
|
+
['0xfacet-rubidity', '>= 0.0.1'],
|
24
|
+
]
|
25
|
+
|
26
|
+
|
27
|
+
self.licenses = ['Public Domain']
|
28
|
+
|
29
|
+
self.spec_extras = {
|
30
|
+
required_ruby_version: '>= 2.3'
|
31
|
+
}
|
32
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
contract :ERC20, abstract: true do
|
4
|
+
event :Transfer, { from: :address, to: :address, amount: :uint256 }
|
5
|
+
event :Approval, { owner: :address, spender: :address, amount: :uint256 }
|
6
|
+
|
7
|
+
string :public, :name
|
8
|
+
string :public, :symbol
|
9
|
+
uint8 :public, :decimals
|
10
|
+
|
11
|
+
uint256 :public, :totalSupply
|
12
|
+
|
13
|
+
mapping ({ address: :uint256 }), :public, :balanceOf
|
14
|
+
mapping ({ address: mapping(address: :uint256) }), :public, :allowance
|
15
|
+
|
16
|
+
constructor(name: :string, symbol: :string, decimals: :uint8) {
|
17
|
+
s.name = name
|
18
|
+
s.symbol = symbol
|
19
|
+
s.decimals = decimals
|
20
|
+
}
|
21
|
+
|
22
|
+
function :approve, { spender: :address, amount: :uint256 }, :public, :virtual, returns: :bool do
|
23
|
+
s.allowance[msg.sender][spender] = amount
|
24
|
+
|
25
|
+
emit :Approval, owner: msg.sender, spender: spender, amount: amount
|
26
|
+
|
27
|
+
return true
|
28
|
+
end
|
29
|
+
|
30
|
+
function :transfer, { to: :address, amount: :uint256 }, :public, :virtual, returns: :bool do
|
31
|
+
require(s.balanceOf[msg.sender] >= amount, "Insufficient balance")
|
32
|
+
|
33
|
+
s.balanceOf[msg.sender] -= amount
|
34
|
+
s.balanceOf[to] += amount
|
35
|
+
|
36
|
+
emit :Transfer, from: msg.sender, to: to, amount: amount
|
37
|
+
|
38
|
+
return true
|
39
|
+
end
|
40
|
+
|
41
|
+
function :transferFrom, {
|
42
|
+
from: :address,
|
43
|
+
to: :address,
|
44
|
+
amount: :uint256
|
45
|
+
}, :public, :virtual, returns: :bool do
|
46
|
+
allowed = s.allowance[from][msg.sender]
|
47
|
+
|
48
|
+
require(s.balanceOf[from] >= amount, "Insufficient balance")
|
49
|
+
require(allowed >= amount, "Insufficient allowance")
|
50
|
+
|
51
|
+
s.allowance[from][msg.sender] = allowed - amount
|
52
|
+
|
53
|
+
s.balanceOf[from] -= amount
|
54
|
+
s.balanceOf[to] += amount
|
55
|
+
|
56
|
+
emit :Transfer, from: from, to: to, amount: amount
|
57
|
+
|
58
|
+
return true
|
59
|
+
end
|
60
|
+
|
61
|
+
function :_mint, { to: :address, amount: :uint256 }, :internal, :virtual do
|
62
|
+
s.totalSupply += amount
|
63
|
+
s.balanceOf[to] += amount
|
64
|
+
|
65
|
+
emit :Transfer, from: address(0), to: to, amount: amount
|
66
|
+
end
|
67
|
+
|
68
|
+
function :_burn, { from: :address, amount: :uint256 }, :internal, :virtual do
|
69
|
+
require(s.balanceOf[from] >= amount, "Insufficient balance")
|
70
|
+
|
71
|
+
s.balanceOf[from] -= amount
|
72
|
+
s.totalSupply -= amount
|
73
|
+
|
74
|
+
emit :Transfer, from: from, to: address(0), amount: amount
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
contract :ERC721, abstract: true do
|
4
|
+
event :Transfer, { from: :address, to: :address, id: :uint256 }
|
5
|
+
event :Approval, { owner: :address, spender: :address, id: :uint256 }
|
6
|
+
event :ApprovalForAll, { owner: :address, operator: :address, approved: :bool }
|
7
|
+
|
8
|
+
string :public, :name
|
9
|
+
string :public, :symbol
|
10
|
+
|
11
|
+
mapping ({ uint256: :address }), :internal, :_ownerOf
|
12
|
+
mapping ({ address: :uint256 }), :internal, :_balanceOf
|
13
|
+
|
14
|
+
mapping ({ uint256: :address }), :public, :getApproved
|
15
|
+
mapping ({ address: mapping(address: :bool) }), :public, :isApprovedForAll
|
16
|
+
|
17
|
+
constructor(name: :string, symbol: :string) {
|
18
|
+
s.name = name
|
19
|
+
s.symbol = symbol
|
20
|
+
}
|
21
|
+
|
22
|
+
function :ownerOf, { id: :uint256 }, :public, :view, :virtual, returns: :address do
|
23
|
+
owner = s._ownerOf[id]
|
24
|
+
require(owner != address(0), "ERC721: owner query for nonexistent token")
|
25
|
+
|
26
|
+
return owner
|
27
|
+
end
|
28
|
+
|
29
|
+
function :balanceOf, { owner: :address }, :public, :view, :virtual, returns: :uint256 do
|
30
|
+
require(owner != address(0), "ERC721: balance query for nonexistent owner")
|
31
|
+
|
32
|
+
return s._balanceOf[owner]
|
33
|
+
end
|
34
|
+
|
35
|
+
function :approve, { spender: :address, id: :uint256 }, :public, :virtual do
|
36
|
+
owner = s._ownerOf[id];
|
37
|
+
|
38
|
+
require(msg.sender == owner || s.isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
|
39
|
+
|
40
|
+
s.getApproved[id] = spender;
|
41
|
+
|
42
|
+
emit :Approval, owner: owner, spender: spender, id: id
|
43
|
+
end
|
44
|
+
|
45
|
+
function :setApprovalForAll, { operator: :address, bool: :approved }, :public, :virtual do
|
46
|
+
s.isApprovedForAll[msg.sender][operator] = approved;
|
47
|
+
|
48
|
+
emit :ApprovalForAll, owner: msg.sender, operator: operator, approved: approved
|
49
|
+
end
|
50
|
+
|
51
|
+
function :transferFrom, { from: :address, to: :address, id: :uint256 }, :public, :virtual do
|
52
|
+
require(from == s._ownerOf[id], "ERC721: transfer of token that is not own");
|
53
|
+
require(to != address(0), "ERC721: transfer to the zero address");
|
54
|
+
|
55
|
+
require(
|
56
|
+
msg.sender == from ||
|
57
|
+
s.getApproved[id] == msg.sender ||
|
58
|
+
isApprovedForAll[from][msg.sender],
|
59
|
+
"NOT_AUTHORIZED"
|
60
|
+
);
|
61
|
+
|
62
|
+
s._balanceOf[from] -= 1;
|
63
|
+
s._balanceOf[to] += 1;
|
64
|
+
|
65
|
+
s._ownerOf[id] = to;
|
66
|
+
|
67
|
+
s.getApproved[id] = address(0);
|
68
|
+
|
69
|
+
return nil
|
70
|
+
end
|
71
|
+
|
72
|
+
function :_exists, { id: :uint256 }, :internal, :virtual, returns: :bool do
|
73
|
+
return s._ownerOf[id] != address(0)
|
74
|
+
end
|
75
|
+
|
76
|
+
function :_mint, { to: :address, id: :uint256 }, :internal, :virtual do
|
77
|
+
require(to != address(0), "ERC721: mint to the zero address");
|
78
|
+
require(s._ownerOf[id] == address(0), "ERC721: token already minted");
|
79
|
+
|
80
|
+
s._balanceOf[to] += 1;
|
81
|
+
|
82
|
+
s._ownerOf[id] = to;
|
83
|
+
|
84
|
+
emit :Transfer, from: address(0), to: to, id: id
|
85
|
+
end
|
86
|
+
|
87
|
+
function :_burn, { id: :uint256 }, :internal, :virtual do
|
88
|
+
owner = s._ownerOf[id];
|
89
|
+
|
90
|
+
require(owner != address(0), "ERC721: burn of nonexistent token");
|
91
|
+
|
92
|
+
s._balanceOf[owner] -= 1;
|
93
|
+
|
94
|
+
s._ownerOf[id] = address(0);
|
95
|
+
|
96
|
+
s.getApproved[id] = address(0);
|
97
|
+
|
98
|
+
emit :Transfer, from: owner, to: address(0), id: id
|
99
|
+
end
|
100
|
+
|
101
|
+
function :tokenURI, { id: :uint256 }, :public, :view, :virtual, returns: :string do
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
import "ERC20"
|
4
|
+
import "Upgradeable"
|
5
|
+
|
6
|
+
contract :EtherBridge, is: [:ERC20, :Upgradeable], upgradeable: true do
|
7
|
+
event :InitiateWithdrawal, { from: :address, amount: :uint256, withdrawalId: :bytes32 }
|
8
|
+
event :WithdrawalComplete, { to: :address, amounts: [:uint256], withdrawalIds: [:bytes32] }
|
9
|
+
|
10
|
+
address :public, :trustedSmartContract
|
11
|
+
mapping ({ address: :uint256 }), :public, :pendingWithdrawalAmounts
|
12
|
+
mapping ({ address: array(:bytes32) }), :public, :pendingUserWithdrawalIds
|
13
|
+
|
14
|
+
bool :public, :bridgeOutPaused
|
15
|
+
|
16
|
+
constructor(
|
17
|
+
name: :string,
|
18
|
+
symbol: :string,
|
19
|
+
trustedSmartContract: :address
|
20
|
+
) {
|
21
|
+
ERC20.constructor(name: name, symbol: symbol, decimals: 18)
|
22
|
+
Upgradeable.constructor(upgradeAdmin: msg.sender)
|
23
|
+
|
24
|
+
s.trustedSmartContract = trustedSmartContract
|
25
|
+
}
|
26
|
+
|
27
|
+
function :bridgeIn, { to: :address, amount: :uint256 }, :public do
|
28
|
+
require(
|
29
|
+
msg.sender == s.trustedSmartContract,
|
30
|
+
"Only the trusted smart contract can bridge in tokens"
|
31
|
+
)
|
32
|
+
|
33
|
+
_mint(to: to, amount: amount)
|
34
|
+
end
|
35
|
+
|
36
|
+
function :setBridgeOutPause, { newState: :bool }, :public do
|
37
|
+
require(msg.sender == s.upgradeAdmin, "Only the pause admin can pause bridge outs")
|
38
|
+
|
39
|
+
s.bridgeOutPaused = newState
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
function :bridgeOut, { amount: :uint256 }, :public do
|
44
|
+
require(!s.bridgeOutPaused, "Bridge out is paused")
|
45
|
+
|
46
|
+
_burn(from: msg.sender, amount: amount)
|
47
|
+
|
48
|
+
withdrawalId = esc.currentTransactionHash
|
49
|
+
|
50
|
+
s.pendingWithdrawalAmounts[msg.sender] += amount
|
51
|
+
s.pendingUserWithdrawalIds[msg.sender].push(withdrawalId)
|
52
|
+
|
53
|
+
emit :InitiateWithdrawal, from: msg.sender, amount: amount, withdrawalId: withdrawalId
|
54
|
+
end
|
55
|
+
|
56
|
+
function :markWithdrawalComplete, {
|
57
|
+
to: :address,
|
58
|
+
amounts: [:uint256],
|
59
|
+
withdrawalIds: [:bytes32]
|
60
|
+
}, :public do
|
61
|
+
require(
|
62
|
+
msg.sender == s.trustedSmartContract,
|
63
|
+
"Only the trusted smart contract can mark withdrawals as complete"
|
64
|
+
)
|
65
|
+
|
66
|
+
for i in 0...withdrawalIds.length
|
67
|
+
withdrawalId = withdrawalIds[i]
|
68
|
+
amount = amounts[i]
|
69
|
+
|
70
|
+
require(
|
71
|
+
s.pendingWithdrawalAmounts[to] >= amount,
|
72
|
+
"Insufficient pending withdrawal"
|
73
|
+
)
|
74
|
+
|
75
|
+
require(
|
76
|
+
_removeFirstOccurenceOfValueFromArray(
|
77
|
+
s.pendingUserWithdrawalIds[to],
|
78
|
+
withdrawalId
|
79
|
+
),
|
80
|
+
"Withdrawal id not found"
|
81
|
+
)
|
82
|
+
|
83
|
+
s.pendingWithdrawalAmounts[to] -= amount
|
84
|
+
end
|
85
|
+
|
86
|
+
emit :WithdrawalComplete, to: to, amounts: amounts, withdrawalIds: withdrawalIds
|
87
|
+
end
|
88
|
+
|
89
|
+
function :getPendingWithdrawalsForUser, { user: :address }, :public, :view, returns: [:bytes32] do
|
90
|
+
return s.pendingUserWithdrawalIds[user]
|
91
|
+
end
|
92
|
+
|
93
|
+
function :_removeFirstOccurenceOfValueFromArray, { arr: array(:bytes32), value: :bytes32 }, :internal, returns: :bool do
|
94
|
+
for i in 0...arr.length
|
95
|
+
if arr[i] == value
|
96
|
+
return _removeItemAtIndex(arr: arr, indexToRemove: i)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
return false
|
101
|
+
end
|
102
|
+
|
103
|
+
function :_removeItemAtIndex, { arr: array(:bytes32), indexToRemove: :uint256 }, :internal, returns: :bool do
|
104
|
+
lastIndex = arr.length - 1
|
105
|
+
|
106
|
+
if lastIndex != indexToRemove
|
107
|
+
lastItem = arr[lastIndex]
|
108
|
+
arr[indexToRemove] = lastItem
|
109
|
+
end
|
110
|
+
|
111
|
+
arr.pop
|
112
|
+
|
113
|
+
return true
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
import "ERC20"
|
4
|
+
import "Upgradeable"
|
5
|
+
|
6
|
+
contract :EtherBridgeV2, is: [:ERC20, :Upgradeable], upgradeable: true do
|
7
|
+
event :BridgedIn, { to: :address, amount: :uint256 }
|
8
|
+
event :InitiateWithdrawal, { from: :address, amount: :uint256, withdrawalId: :bytes32 }
|
9
|
+
event :WithdrawalComplete, { to: :address, amount: :uint256, withdrawalId: :bytes32 }
|
10
|
+
|
11
|
+
address :public, :trustedSmartContract
|
12
|
+
|
13
|
+
mapping ({ address: :uint256 }), :public, :pendingWithdrawalAmounts
|
14
|
+
mapping ({ address: array(:bytes32) }), :public, :pendingUserWithdrawalIds
|
15
|
+
|
16
|
+
mapping ({ bytes32: :uint256 }), :public, :withdrawalIdAmount
|
17
|
+
mapping ({ address: :bytes32 }), :public, :userWithdrawalId
|
18
|
+
|
19
|
+
constructor(
|
20
|
+
name: :string,
|
21
|
+
symbol: :string,
|
22
|
+
trustedSmartContract: :address
|
23
|
+
) {
|
24
|
+
require(trustedSmartContract != address(0), "Invalid smart contract")
|
25
|
+
|
26
|
+
ERC20.constructor(name: name, symbol: symbol, decimals: 18)
|
27
|
+
Upgradeable.constructor(upgradeAdmin: msg.sender)
|
28
|
+
|
29
|
+
s.trustedSmartContract = trustedSmartContract
|
30
|
+
}
|
31
|
+
|
32
|
+
function :onUpgrade, { usersToProcess: [:address] }, :public do
|
33
|
+
require(msg.sender == address(this), "Only the contract can call this function")
|
34
|
+
|
35
|
+
for i in 0...usersToProcess.length
|
36
|
+
user = usersToProcess[i]
|
37
|
+
|
38
|
+
require(s.pendingUserWithdrawalIds[user].length == 1, "Migration not possible")
|
39
|
+
|
40
|
+
withdrawalId = s.pendingUserWithdrawalIds[user].pop
|
41
|
+
amount = s.pendingWithdrawalAmounts[user]
|
42
|
+
|
43
|
+
s.pendingWithdrawalAmounts[user] = 0
|
44
|
+
s.userWithdrawalId[user] = withdrawalId
|
45
|
+
|
46
|
+
s.withdrawalIdAmount[withdrawalId] = amount
|
47
|
+
end
|
48
|
+
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
function :bridgeIn, { to: :address, amount: :uint256 }, :public do
|
53
|
+
require(
|
54
|
+
msg.sender == s.trustedSmartContract,
|
55
|
+
"Only the trusted smart contract can bridge in tokens"
|
56
|
+
)
|
57
|
+
|
58
|
+
_mint(to: to, amount: amount)
|
59
|
+
emit :BridgedIn, to: to, amount: amount
|
60
|
+
end
|
61
|
+
|
62
|
+
function :bridgeOut, { amount: :uint256 }, :public do
|
63
|
+
withdrawalId = esc.currentTransactionHash
|
64
|
+
require(
|
65
|
+
s.userWithdrawalId[msg.sender] == bytes32(0),
|
66
|
+
"Withdrawal pending"
|
67
|
+
)
|
68
|
+
require(
|
69
|
+
s.withdrawalIdAmount[withdrawalId] == 0,
|
70
|
+
"Already bridged out"
|
71
|
+
)
|
72
|
+
require(amount > 0, "Invalid amount")
|
73
|
+
|
74
|
+
s.userWithdrawalId[msg.sender] = withdrawalId
|
75
|
+
s.withdrawalIdAmount[withdrawalId] = amount
|
76
|
+
|
77
|
+
_burn(from: msg.sender, amount: amount)
|
78
|
+
emit :InitiateWithdrawal, from: msg.sender, amount: amount, withdrawalId: withdrawalId
|
79
|
+
end
|
80
|
+
|
81
|
+
function :markWithdrawalComplete, {
|
82
|
+
to: :address,
|
83
|
+
withdrawalId: :bytes32
|
84
|
+
}, :public do
|
85
|
+
require(
|
86
|
+
msg.sender == s.trustedSmartContract,
|
87
|
+
"Only the trusted smart contract can mark withdrawals as complete"
|
88
|
+
)
|
89
|
+
require(
|
90
|
+
s.userWithdrawalId[to] == withdrawalId,
|
91
|
+
"Withdrawal id not found"
|
92
|
+
)
|
93
|
+
|
94
|
+
amount = s.withdrawalIdAmount[withdrawalId]
|
95
|
+
s.withdrawalIdAmount[withdrawalId] = 0
|
96
|
+
s.userWithdrawalId[to] = bytes32(0)
|
97
|
+
|
98
|
+
emit :WithdrawalComplete, to: to, amount: amount, withdrawalId: withdrawalId
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
import "ERC20"
|
4
|
+
import "Upgradeable"
|
5
|
+
|
6
|
+
contract :EthscriptionERC20Bridge, is: [:ERC20, :Upgradeable], upgradeable: true do
|
7
|
+
event :BridgedIn, { to: :address, amount: :uint256 }
|
8
|
+
event :InitiateWithdrawal, { from: :address, amount: :uint256, withdrawalId: :bytes32 }
|
9
|
+
event :WithdrawalComplete, { to: :address, amount: :uint256, withdrawalId: :bytes32 }
|
10
|
+
|
11
|
+
uint256 :public, :mintAmount
|
12
|
+
address :public, :trustedSmartContract
|
13
|
+
|
14
|
+
mapping ({ address: :uint256 }), :public, :bridgedInAmount
|
15
|
+
mapping ({ bytes32: :uint256 }), :public, :withdrawalIdAmount
|
16
|
+
mapping ({ address: :bytes32 }), :public, :userWithdrawalId
|
17
|
+
|
18
|
+
constructor(
|
19
|
+
name: :string,
|
20
|
+
symbol: :string,
|
21
|
+
mintAmount: :uint256,
|
22
|
+
trustedSmartContract: :address
|
23
|
+
) {
|
24
|
+
require(mintAmount > 0, "Invalid mint amount")
|
25
|
+
require(trustedSmartContract != address(0), "Invalid smart contract")
|
26
|
+
|
27
|
+
ERC20.constructor(name: name, symbol: symbol, decimals: 18)
|
28
|
+
Upgradeable.constructor(upgradeAdmin: msg.sender)
|
29
|
+
|
30
|
+
s.mintAmount = mintAmount
|
31
|
+
s.trustedSmartContract = trustedSmartContract
|
32
|
+
}
|
33
|
+
|
34
|
+
function :bridgeIn, { to: :address, amount: :uint256 }, :public do
|
35
|
+
require(
|
36
|
+
msg.sender == s.trustedSmartContract,
|
37
|
+
"Only the trusted smart contract can bridge in tokens"
|
38
|
+
)
|
39
|
+
|
40
|
+
s.bridgedInAmount[to] += amount
|
41
|
+
|
42
|
+
_mint(to: to, amount: amount * s.mintAmount * 1.ether)
|
43
|
+
emit :BridgedIn, to: to, amount: amount
|
44
|
+
end
|
45
|
+
|
46
|
+
function :bridgeOut, { amount: :uint256 }, :public do
|
47
|
+
withdrawalId = esc.currentTransactionHash
|
48
|
+
require(
|
49
|
+
s.userWithdrawalId[msg.sender] == bytes32(0),
|
50
|
+
"Withdrawal pending"
|
51
|
+
)
|
52
|
+
require(
|
53
|
+
s.withdrawalIdAmount[withdrawalId] == 0,
|
54
|
+
"Already bridged out"
|
55
|
+
)
|
56
|
+
require(
|
57
|
+
s.bridgedInAmount[msg.sender] >= amount,
|
58
|
+
"Not enough bridged in"
|
59
|
+
)
|
60
|
+
require(amount > 0, "Invalid amount")
|
61
|
+
|
62
|
+
s.userWithdrawalId[msg.sender] = withdrawalId
|
63
|
+
s.withdrawalIdAmount[withdrawalId] = amount
|
64
|
+
s.bridgedInAmount[msg.sender] -= amount
|
65
|
+
|
66
|
+
_burn(from: msg.sender, amount: amount * s.mintAmount * 1.ether)
|
67
|
+
emit :InitiateWithdrawal, from: msg.sender, amount: amount, withdrawalId: withdrawalId
|
68
|
+
end
|
69
|
+
|
70
|
+
function :markWithdrawalComplete, {
|
71
|
+
to: :address,
|
72
|
+
withdrawalId: :bytes32
|
73
|
+
}, :public do
|
74
|
+
require(
|
75
|
+
msg.sender == s.trustedSmartContract,
|
76
|
+
"Only the trusted smart contract can mark withdrawals as complete"
|
77
|
+
)
|
78
|
+
require(
|
79
|
+
s.userWithdrawalId[to] == withdrawalId,
|
80
|
+
"Withdrawal id not found"
|
81
|
+
)
|
82
|
+
|
83
|
+
amount = s.withdrawalIdAmount[withdrawalId]
|
84
|
+
s.withdrawalIdAmount[withdrawalId] = 0
|
85
|
+
s.userWithdrawalId[to] = bytes32(0)
|
86
|
+
|
87
|
+
emit :WithdrawalComplete, to: to, amount: amount, withdrawalId: withdrawalId
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
import 'ERC721'
|
4
|
+
|
5
|
+
contract :GenerativeERC721, is: :ERC721 do
|
6
|
+
string :public, :generativeScript
|
7
|
+
mapping ({ uint256: :uint256 }), :public, :tokenIdToSeed
|
8
|
+
|
9
|
+
uint256 :public, :totalSupply
|
10
|
+
uint256 :public, :maxSupply
|
11
|
+
uint256 :public, :maxPerAddress
|
12
|
+
string :public, :description
|
13
|
+
|
14
|
+
constructor(
|
15
|
+
name: :string,
|
16
|
+
symbol: :string,
|
17
|
+
generativeScript: :string,
|
18
|
+
maxSupply: :uint256,
|
19
|
+
description: :string,
|
20
|
+
maxPerAddress: :uint256
|
21
|
+
) {
|
22
|
+
ERC721.constructor(name: name, symbol: symbol)
|
23
|
+
|
24
|
+
s.maxSupply = maxSupply
|
25
|
+
s.maxPerAddress = maxPerAddress
|
26
|
+
s.description = description
|
27
|
+
s.generativeScript = generativeScript
|
28
|
+
}
|
29
|
+
|
30
|
+
function :mint, { amount: :uint256 }, :public, returns: :uint256 do
|
31
|
+
require(amount > 0, 'Amount must be positive')
|
32
|
+
require(amount + s._balanceOf[msg.sender] <= s.maxPerAddress, 'Exceeded mint limit')
|
33
|
+
require(amount + s.totalSupply <= s.maxSupply, 'Exceeded max supply')
|
34
|
+
|
35
|
+
hash = blockhash(block.number).cast(:uint256) % (2 ** 48)
|
36
|
+
|
37
|
+
amount.times do |id|
|
38
|
+
tokenId = s.totalSupply + id
|
39
|
+
seed = hash + tokenId
|
40
|
+
|
41
|
+
s.tokenIdToSeed[tokenId] = seed
|
42
|
+
|
43
|
+
_mint(to: msg.sender, id: tokenId)
|
44
|
+
end
|
45
|
+
|
46
|
+
s.totalSupply += amount
|
47
|
+
end
|
48
|
+
|
49
|
+
function :tokenURI, { id: :uint256 }, :public, :view, :override, returns: :string do
|
50
|
+
require(_exists(id: id), 'ERC721Metadata: URI query for nonexistent token')
|
51
|
+
|
52
|
+
html = getHTML(seed: s.tokenIdToSeed[id])
|
53
|
+
|
54
|
+
html_as_base_64_data_uri = "data:text/html;base64," + esc.base64Encode(html)
|
55
|
+
|
56
|
+
json_data = {
|
57
|
+
name: "#{s.name} ##{string(id)}",
|
58
|
+
description: s.description,
|
59
|
+
animation_url: html_as_base_64_data_uri,
|
60
|
+
}.to_json
|
61
|
+
|
62
|
+
return "data:application/json,#{json_data}"
|
63
|
+
end
|
64
|
+
|
65
|
+
function :getHTML, { seed: :uint256 }, :public, :view, returns: :string do
|
66
|
+
<<~HTML
|
67
|
+
<html>
|
68
|
+
<head>
|
69
|
+
<style>
|
70
|
+
body,
|
71
|
+
html {
|
72
|
+
width: 100%;
|
73
|
+
height: 100%;
|
74
|
+
margin: 0;
|
75
|
+
padding: 0;
|
76
|
+
overflow: hidden;
|
77
|
+
display: block;
|
78
|
+
}
|
79
|
+
|
80
|
+
#canvas {
|
81
|
+
position: absolute;
|
82
|
+
}
|
83
|
+
</style>
|
84
|
+
</head>
|
85
|
+
<body>
|
86
|
+
<canvas id="canvas"></canvas>
|
87
|
+
</body>
|
88
|
+
<script>
|
89
|
+
window.SEED = #{string(seed)};
|
90
|
+
#{s.generativeScript}
|
91
|
+
</script>
|
92
|
+
</html>
|
93
|
+
HTML
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
import 'ERC721'
|
4
|
+
|
5
|
+
contract :OpenEditionERC721, is: :ERC721 do
|
6
|
+
string :public, :contentURI
|
7
|
+
uint256 :public, :maxPerAddress
|
8
|
+
uint256 :public, :totalSupply
|
9
|
+
string :public, :description
|
10
|
+
|
11
|
+
datetime :public, :mintStart
|
12
|
+
datetime :public, :mintEnd
|
13
|
+
|
14
|
+
constructor(
|
15
|
+
name: :string,
|
16
|
+
symbol: :string,
|
17
|
+
contentURI: :string,
|
18
|
+
maxPerAddress: :uint256,
|
19
|
+
description: :string,
|
20
|
+
mintStart: :datetime,
|
21
|
+
mintEnd: :datetime
|
22
|
+
) {
|
23
|
+
ERC721.constructor(name: name, symbol: symbol)
|
24
|
+
|
25
|
+
s.maxPerAddress = maxPerAddress
|
26
|
+
s.description = description
|
27
|
+
s.contentURI = contentURI
|
28
|
+
s.mintStart = mintStart
|
29
|
+
s.mintEnd = mintEnd
|
30
|
+
}
|
31
|
+
|
32
|
+
function :mint, { amount: :uint256 }, :public, returns: :uint256 do
|
33
|
+
require(amount > 0, 'Amount must be positive')
|
34
|
+
require(amount + s._balanceOf[msg.sender] <= s.maxPerAddress, 'Exceeded mint limit')
|
35
|
+
require(block.timestamp >= s.mintStart, 'Minting has not started')
|
36
|
+
require(block.timestamp < s.mintEnd, 'Minting has ended')
|
37
|
+
|
38
|
+
amount.times do |id|
|
39
|
+
_mint(to: msg.sender, id: s.totalSupply + id)
|
40
|
+
end
|
41
|
+
|
42
|
+
s.totalSupply += amount
|
43
|
+
end
|
44
|
+
|
45
|
+
function :tokenURI, { id: :uint256 }, :public, :view, :override, returns: :string do
|
46
|
+
require(_exists(id: id), 'ERC721Metadata: URI query for nonexistent token')
|
47
|
+
|
48
|
+
json_data = {
|
49
|
+
name: "#{s.name} ##{string(id)}",
|
50
|
+
description: s.description,
|
51
|
+
image: s.contentURI,
|
52
|
+
}.to_json
|
53
|
+
|
54
|
+
return "data:application/json,#{json_data}"
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
import 'ERC20'
|
4
|
+
|
5
|
+
contract :PublicMintERC20, is: :ERC20 do
|
6
|
+
uint256 :public, :maxSupply
|
7
|
+
uint256 :public, :perMintLimit
|
8
|
+
|
9
|
+
constructor(
|
10
|
+
name: :string,
|
11
|
+
symbol: :string,
|
12
|
+
maxSupply: :uint256,
|
13
|
+
perMintLimit: :uint256,
|
14
|
+
decimals: :uint8
|
15
|
+
) {
|
16
|
+
ERC20.constructor(name: name, symbol: symbol, decimals: decimals)
|
17
|
+
s.maxSupply = maxSupply
|
18
|
+
s.perMintLimit = perMintLimit
|
19
|
+
}
|
20
|
+
|
21
|
+
function :mint, { amount: :uint256 }, :public do
|
22
|
+
require(amount > 0, 'Amount must be positive')
|
23
|
+
require(amount <= s.perMintLimit, 'Exceeded mint limit')
|
24
|
+
|
25
|
+
require(s.totalSupply + amount <= s.maxSupply, 'Exceeded max supply')
|
26
|
+
|
27
|
+
_mint(to: msg.sender, amount: amount)
|
28
|
+
end
|
29
|
+
|
30
|
+
function :airdrop, { to: :address, amount: :uint256 }, :public do
|
31
|
+
require(amount > 0, 'Amount must be positive')
|
32
|
+
require(amount <= s.perMintLimit, 'Exceeded mint limit')
|
33
|
+
|
34
|
+
require(s.totalSupply + amount <= s.maxSupply, 'Exceeded max supply')
|
35
|
+
|
36
|
+
_mint(to: to, amount: amount)
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
import 'ERC20'
|
4
|
+
|
5
|
+
contract :UnsafeNoApprovalERC20, is: :ERC20 do
|
6
|
+
constructor(
|
7
|
+
name: :string,
|
8
|
+
symbol: :string,
|
9
|
+
) {
|
10
|
+
ERC20.constructor(name: name, symbol: symbol, decimals: 18)
|
11
|
+
}
|
12
|
+
|
13
|
+
function :mint, { amount: :uint256 }, :public do
|
14
|
+
require(amount > 0, 'Amount must be positive')
|
15
|
+
|
16
|
+
_mint(to: msg.sender, amount: amount)
|
17
|
+
end
|
18
|
+
|
19
|
+
function :airdrop, { to: :address, amount: :uint256 }, :public do
|
20
|
+
require(amount > 0, 'Amount must be positive')
|
21
|
+
|
22
|
+
_mint(to: to, amount: amount)
|
23
|
+
end
|
24
|
+
|
25
|
+
function :transferFrom, {
|
26
|
+
from: :address,
|
27
|
+
to: :address,
|
28
|
+
amount: :uint256
|
29
|
+
}, :public, :override, returns: :bool do
|
30
|
+
require(s.balanceOf[from] >= amount, 'Insufficient balance')
|
31
|
+
|
32
|
+
s.balanceOf[from] -= amount
|
33
|
+
s.balanceOf[to] += amount
|
34
|
+
|
35
|
+
emit :Transfer, from: from, to: to, amount: amount
|
36
|
+
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
pragma :rubidity, "1.0.0"
|
2
|
+
|
3
|
+
contract :Upgradeable, abstract: true do
|
4
|
+
address :public, :upgradeAdmin
|
5
|
+
|
6
|
+
event :ContractUpgraded, { oldHash: :bytes32, newHash: :bytes32 }
|
7
|
+
event :UpgradeAdminChanged, { newUpgradeAdmin: :address }
|
8
|
+
|
9
|
+
constructor(upgradeAdmin: :address) {
|
10
|
+
s.upgradeAdmin = upgradeAdmin
|
11
|
+
}
|
12
|
+
|
13
|
+
function :setUpgradeAdmin, { newUpgradeAdmin: :address }, :public do
|
14
|
+
require(msg.sender == s.upgradeAdmin, "NOT_AUTHORIZED")
|
15
|
+
|
16
|
+
s.upgradeAdmin = newUpgradeAdmin
|
17
|
+
|
18
|
+
emit :UpgradeAdminChanged, newUpgradeAdmin: newUpgradeAdmin
|
19
|
+
end
|
20
|
+
|
21
|
+
function :upgradeAndCall, { newHash: :bytes32, migrationCalldata: :string }, :public do
|
22
|
+
upgrade(newHash: newHash)
|
23
|
+
|
24
|
+
(success, data) = address(this).call(migrationCalldata)
|
25
|
+
require(success, "Migration failed")
|
26
|
+
end
|
27
|
+
|
28
|
+
function :upgrade, { newHash: :bytes32 }, :public do
|
29
|
+
currentHash = esc.getImplementationHash
|
30
|
+
|
31
|
+
require(msg.sender == s.upgradeAdmin, "NOT_AUTHORIZED")
|
32
|
+
|
33
|
+
esc.upgradeContract(newHash)
|
34
|
+
|
35
|
+
emit :ContractUpgraded, oldHash: currentHash, newHash: newHash
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: 0xfacet-contracts
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gerald Bauer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-11-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: 0xfacet-rubidity
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rdoc
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.0'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '7'
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '4.0'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '7'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: hoe
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '4.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '4.0'
|
61
|
+
description: 0xfacet-contracts - rubidity o.g. standard contracts (incl. ERC20, PublicMintERC20,
|
62
|
+
ERC721, GenerativeERC721, etc.)
|
63
|
+
email: gerald.bauer@gmail.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files:
|
67
|
+
- CHANGELOG.md
|
68
|
+
- Manifest.txt
|
69
|
+
- README.md
|
70
|
+
files:
|
71
|
+
- CHANGELOG.md
|
72
|
+
- Manifest.txt
|
73
|
+
- README.md
|
74
|
+
- Rakefile
|
75
|
+
- lib/0xfacet/contracts.rb
|
76
|
+
- lib/0xfacet/contracts/ERC20.rb
|
77
|
+
- lib/0xfacet/contracts/ERC721.rb
|
78
|
+
- lib/0xfacet/contracts/EtherBridge.rb
|
79
|
+
- lib/0xfacet/contracts/EtherBridgeV2.rb
|
80
|
+
- lib/0xfacet/contracts/EthscriptionERC20Bridge.rb
|
81
|
+
- lib/0xfacet/contracts/GenerativeERC721.rb
|
82
|
+
- lib/0xfacet/contracts/OpenEditionERC721.rb
|
83
|
+
- lib/0xfacet/contracts/PublicMintERC20.rb
|
84
|
+
- lib/0xfacet/contracts/UnsafeNoApprovalERC20.rb
|
85
|
+
- lib/0xfacet/contracts/Upgradeable.rb
|
86
|
+
homepage: https://github.com/s6ruby/rubidity.review
|
87
|
+
licenses:
|
88
|
+
- Public Domain
|
89
|
+
metadata: {}
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options:
|
92
|
+
- "--main"
|
93
|
+
- README.md
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '2.3'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubygems_version: 3.4.10
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: 0xfacet-contracts - rubidity o.g. standard contracts (incl. ERC20, PublicMintERC20,
|
111
|
+
ERC721, GenerativeERC721, etc.)
|
112
|
+
test_files: []
|