deploy.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import sys
  2. from terra_sdk.client.lcd import AsyncLCDClient
  3. from terra_sdk.client.localterra import AsyncLocalTerra
  4. from terra_sdk.core.auth import StdFee
  5. import asyncio
  6. from terra_sdk.core.wasm import (
  7. MsgStoreCode,
  8. MsgInstantiateContract,
  9. MsgExecuteContract,
  10. MsgMigrateContract,
  11. )
  12. from terra_sdk.key.mnemonic import MnemonicKey
  13. from terra_sdk.util.contract import get_code_id, get_contract_address, read_file_as_b64
  14. import os
  15. import base64
  16. import pprint
  17. if len(sys.argv) != 8:
  18. print(
  19. "Usage: deploy.py <lcd_url> <chain_id> <mnemonic> <gov_chain> <gov_address> <initial_guardian> <expiration_time>")
  20. exit(1)
  21. gas_prices = {
  22. "uluna": "0.15",
  23. "usdr": "0.1018",
  24. "uusd": "0.15",
  25. "ukrw": "178.05",
  26. "umnt": "431.6259",
  27. "ueur": "0.125",
  28. "ucny": "0.97",
  29. "ujpy": "16",
  30. "ugbp": "0.11",
  31. "uinr": "11",
  32. "ucad": "0.19",
  33. "uchf": "0.13",
  34. "uaud": "0.19",
  35. "usgd": "0.2",
  36. }
  37. lt = AsyncLocalTerra(gas_prices={"uusd": "0.15"}, url="http://terra-lcd:1317")
  38. terra = AsyncLCDClient(
  39. sys.argv[1], sys.argv[2], gas_prices=gas_prices
  40. )
  41. deployer = terra.wallet(MnemonicKey(
  42. mnemonic=sys.argv[3]))
  43. sequence = asyncio.get_event_loop().run_until_complete(deployer.sequence())
  44. async def sign_and_broadcast(*msgs):
  45. global sequence
  46. try:
  47. tx = await deployer.create_and_sign_tx(
  48. msgs=msgs, fee=StdFee(30000000, "20000000uusd"), sequence=sequence
  49. )
  50. result = await terra.tx.broadcast(tx)
  51. sequence += 1
  52. if result.is_tx_error():
  53. raise Exception(result.raw_log)
  54. return result
  55. except:
  56. sequence = await deployer.sequence()
  57. raise
  58. async def store_contract(contract_name):
  59. parent_dir = os.path.dirname(__file__)
  60. contract_bytes = read_file_as_b64(f"{parent_dir}/../artifacts/{contract_name}.wasm")
  61. store_code = MsgStoreCode(deployer.key.acc_address, contract_bytes)
  62. result = await sign_and_broadcast(store_code)
  63. code_id = get_code_id(result)
  64. print(f"Code id for {contract_name} is {code_id}")
  65. return code_id
  66. async def store_contracts():
  67. parent_dir = os.path.dirname(__file__)
  68. contract_names = [
  69. i[:-5] for i in sorted(os.listdir(f"{parent_dir}/../artifacts"), reverse = True) if i.endswith(".wasm")
  70. ]
  71. return {
  72. contract_name: await store_contract(contract_name)
  73. for contract_name in contract_names
  74. }
  75. class ContractQuerier:
  76. def __init__(self, address):
  77. self.address = address
  78. def __getattr__(self, item):
  79. async def result_fxn(**kwargs):
  80. kwargs = convert_contracts_to_addr(kwargs)
  81. return await terra.wasm.contract_query(self.address, {item: kwargs})
  82. return result_fxn
  83. class Contract:
  84. @staticmethod
  85. async def create(code_id, migratable=False, **kwargs):
  86. kwargs = convert_contracts_to_addr(kwargs)
  87. instantiate = MsgInstantiateContract(
  88. deployer.key.acc_address, code_id, kwargs, migratable=migratable
  89. )
  90. result = await sign_and_broadcast(instantiate)
  91. return Contract(get_contract_address(result))
  92. def __init__(self, address):
  93. self.address = address
  94. def __getattr__(self, item):
  95. async def result_fxn(coins=None, **kwargs):
  96. kwargs = convert_contracts_to_addr(kwargs)
  97. execute = MsgExecuteContract(
  98. deployer.key.acc_address, self.address, {item: kwargs}, coins=coins
  99. )
  100. return await sign_and_broadcast(execute)
  101. return result_fxn
  102. @property
  103. def query(self):
  104. return ContractQuerier(self.address)
  105. async def migrate(self, new_code_id):
  106. migrate = MsgMigrateContract(
  107. contract=self.address,
  108. migrate_msg={},
  109. new_code_id=new_code_id,
  110. owner=deployer.key.acc_address,
  111. )
  112. return await sign_and_broadcast(migrate)
  113. def convert_contracts_to_addr(obj):
  114. if type(obj) == dict:
  115. return {k: convert_contracts_to_addr(v) for k, v in obj.items()}
  116. if type(obj) in {list, tuple}:
  117. return [convert_contracts_to_addr(i) for i in obj]
  118. if type(obj) == Contract:
  119. return obj.address
  120. return obj
  121. def to_bytes(n, length, byteorder="big"):
  122. return int(n).to_bytes(length, byteorder=byteorder)
  123. def assemble_vaa(emitter_chain, emitter_address, payload):
  124. import time
  125. # version, guardian set index, len signatures
  126. header = to_bytes(1, 1) + to_bytes(0, 4) + to_bytes(0, 1)
  127. # timestamp, nonce, emitter_chain
  128. body = to_bytes(time.time(), 8) + to_bytes(1, 4) + to_bytes(emitter_chain, 2)
  129. # emitter_address, vaa payload
  130. body += emitter_address + payload
  131. return header + body
  132. async def main():
  133. code_ids = await store_contracts()
  134. print(code_ids)
  135. # fake governance contract on solana
  136. GOV_CHAIN = int(sys.argv[4])
  137. GOV_ADDRESS = bytes.fromhex(sys.argv[5])
  138. wormhole = await Contract.create(
  139. code_id=code_ids["wormhole"],
  140. gov_chain=GOV_CHAIN,
  141. gov_address=base64.b64encode(GOV_ADDRESS).decode("utf-8"),
  142. guardian_set_expirity=int(sys.argv[7]),
  143. initial_guardian_set={
  144. "addresses": [{"bytes": base64.b64encode(
  145. bytearray.fromhex(sys.argv[6])).decode("utf-8")}],
  146. "expiration_time": 0},
  147. migratable=True,
  148. )
  149. print("Wormhole contract: {}".format(wormhole.address))
  150. token_bridge = await Contract.create(
  151. code_id=code_ids["token_bridge"],
  152. owner=deployer.key.acc_address,
  153. gov_chain=GOV_CHAIN,
  154. gov_address=base64.b64encode(GOV_ADDRESS).decode("utf-8"),
  155. wormhole_contract=wormhole,
  156. wrapped_asset_code_id=int(code_ids["cw20_wrapped"]),
  157. )
  158. print("Token Bridge contract: {}".format(token_bridge.address))
  159. mock_token = await Contract.create(
  160. code_id=code_ids["cw20_base"],
  161. name="MOCK",
  162. symbol="MCK",
  163. decimals=6,
  164. initial_balances=[{"address": deployer.key.acc_address, "amount": "100000000"}],
  165. mint=None,
  166. )
  167. print("Example Token contract: {}".format(mock_token.address))
  168. registrations = [
  169. '01000000000100c9f4230109e378f7efc0605fb40f0e1869f2d82fda5b1dfad8a5a2dafee85e033d155c18641165a77a2db6a7afbf2745b458616cb59347e89ae0c7aa3e7cc2d400000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e4272696467650100000001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f',
  170. '01000000000100e2e1975d14734206e7a23d90db48a6b5b6696df72675443293c6057dcb936bf224b5df67d32967adeb220d4fe3cb28be515be5608c74aab6adb31099a478db5c01000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e42726964676501000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16'
  171. '01000000000100719b4ada436f614489dbf87593c38ba9aea35aa7b997387f8ae09f819806f5654c8d45b6b751faa0e809ccbc294794885efa205bd8a046669464c7cbfb03d183010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000002c8bb0600000000000000000000000000000000000000000000546f6b656e42726964676501000000040000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16'
  172. ]
  173. for reg in registrations:
  174. await token_bridge.submit_vaa(
  175. data=base64.b64encode(
  176. bytearray.fromhex(reg)
  177. ).decode("utf-8")
  178. )
  179. if __name__ == "__main__":
  180. asyncio.get_event_loop().run_until_complete(main())