0xfacet-contracts 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ ### 0.0.1 / 2023-11-16
2
+
3
+ * Everything is new. First release
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
@@ -0,0 +1,8 @@
1
+
2
+
3
+ puts "hello, 0xfacet contracts!"
4
+
5
+ # note: cannot load rubidity contracts as is - require rubidity loader!
6
+
7
+
8
+
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: []