-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontract.py
131 lines (111 loc) · 3.21 KB
/
contract.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from typing import Dict, List
from hashlib import sha256
import json
import time
from opcodes import *
from signatures import *
from transaction import Transaction
class SmartContract(object):
OPCODES = {
'PUSH': push,
'POP': pop,
'SWAP': swap,
'DUP': dup,
'NOW': now,
'ADD': add,
'SUB': sub,
'MUL': mul,
'DIV': div,
'MOD': mod,
'GREATER': is_greater,
'SSTORE': sstore,
'SLOAD': sload,
'MSTORE': mstore,
'MLOAD': mload,
'SENDER': sender,
'AMOUNT': amount,
'EQUALS': is_equal,
'BALANCE': balance,
'TRANSFER': transfer,
'UNIT': unit,
}
# the stack has a maximum size of 1024
def __init__(contract, balance: int, code: str, storage: dict):
contract.balance = balance
contract.code = code
contract.stack = Stack(contract)
contract.storage = storage
contract.memory = {}
contract.gas_balance = 0
def update_storage(contract, key, value):
contract.storage[key] = value
return value
def update_memory(contract, key, value):
contract.memory[key] = value
return value
def delete_memory(contract):
contract.memory = {}
def send_amount(contract, amount: int, receiver: str):
print(f'SENDING {amount} to {receiver}')
if contract.balance < int(amount):
raise Exception('Invalid Balance')
contract.balance -= int(amount)
# TODO: Update blockchain
def return_leftover_gas(contract):
pass
def execute(contract, gas_balance, sent_amount: int, sender: str, args: dict={}):
contract.gas_balance = gas_balance
contract.sent_amount = sent_amount
contract.sender = sender
contract.memory = args
contract.stack = Stack(contract)
code = contract.code.strip().split('\n')
for row in code:
contract.gas_balance -= 1
if contract.gas_balance < 0:
raise Exception('Ran out of gas')
values = row.strip().split(' ')
# control flow for IF
if values[0] == 'IF':
print('USING LEFT OPTION')
top = contract.stack.pop()
if top == '0':
values[3:]
else:
values = values[1:]
contract.OPCODES[values[0]](contract.stack, *values[1:])
print(contract.stack)
contract.delete_memory()
def basic_example():
code = '''
PUSH magic_word
SLOAD
PUSH my_guess
MLOAD
EQUALS
SENDER
SWAP
BALANCE
SWAP
IF TRANSFER ELSE UNIT
'''
s = SmartContract(33, code, {'magic_word': 'boo'})
s.execute(100, 10, 'fafafafa', {'my_guess': 'boo'})
def basic_example2():
code = '''
SENDER
SLOAD
AMOUNT
PUSH 3
MUL
ADD
SENDER
SSTORE
SENDER
SLOAD
'''
s = SmartContract(33, code, {'magic_word': 'boo', 'fafafafa': '200'})
s.execute(100, 10, 'fafafafa', {'my_guess': 'boo'})
if __name__ == '__main__':
basic_example1()
basic_example2()