github.com/onflow/flow-go@v0.33.17/fvm/evm/stdlib/contract.cdc (about) 1 import "FlowToken" 2 3 access(all) 4 contract EVM { 5 6 /// EVMAddress is an EVM-compatible address 7 access(all) 8 struct EVMAddress { 9 10 /// Bytes of the address 11 access(all) 12 let bytes: [UInt8; 20] 13 14 /// Constructs a new EVM address from the given byte representation 15 init(bytes: [UInt8; 20]) { 16 self.bytes = bytes 17 } 18 19 /// Deposits the given vault into the EVM account with the given address 20 access(all) 21 fun deposit(from: @FlowToken.Vault) { 22 InternalEVM.deposit( 23 from: <-from, 24 to: self.bytes 25 ) 26 } 27 28 /// Balance of the address 29 access(all) 30 fun balance(): Balance { 31 let balance = InternalEVM.balance( 32 address: self.bytes 33 ) 34 35 return Balance(flow: balance) 36 } 37 } 38 39 access(all) 40 struct Balance { 41 42 /// The balance in FLOW 43 access(all) 44 let flow: UFix64 45 46 /// Constructs a new balance, given the balance in FLOW 47 init(flow: UFix64) { 48 self.flow = flow 49 } 50 51 // TODO: 52 // /// Returns the balance in terms of atto-FLOW. 53 // /// Atto-FLOW is the smallest denomination of FLOW inside EVM 54 // access(all) 55 // fun toAttoFlow(): UInt64 56 } 57 58 access(all) 59 resource BridgedAccount { 60 61 access(self) 62 let addressBytes: [UInt8; 20] 63 64 init(addressBytes: [UInt8; 20]) { 65 self.addressBytes = addressBytes 66 } 67 68 /// The EVM address of the bridged account 69 access(all) 70 fun address(): EVMAddress { 71 // Always create a new EVMAddress instance 72 return EVMAddress(bytes: self.addressBytes) 73 } 74 75 /// Get balance of the bridged account 76 access(all) 77 fun balance(): Balance { 78 return self.address().balance() 79 } 80 81 /// Deposits the given vault into the bridged account's balance 82 access(all) 83 fun deposit(from: @FlowToken.Vault) { 84 self.address().deposit(from: <-from) 85 } 86 87 /// Withdraws the balance from the bridged account's balance 88 access(all) 89 fun withdraw(balance: Balance): @FlowToken.Vault { 90 let vault <- InternalEVM.withdraw( 91 from: self.addressBytes, 92 amount: balance.flow 93 ) as! @FlowToken.Vault 94 return <-vault 95 } 96 97 /// Deploys a contract to the EVM environment. 98 /// Returns the address of the newly deployed contract 99 access(all) 100 fun deploy( 101 code: [UInt8], 102 gasLimit: UInt64, 103 value: Balance 104 ): EVMAddress { 105 let addressBytes = InternalEVM.deploy( 106 from: self.addressBytes, 107 code: code, 108 gasLimit: gasLimit, 109 value: value.flow 110 ) 111 return EVMAddress(bytes: addressBytes) 112 } 113 114 /// Calls a function with the given data. 115 /// The execution is limited by the given amount of gas 116 access(all) 117 fun call( 118 to: EVMAddress, 119 data: [UInt8], 120 gasLimit: UInt64, 121 value: Balance 122 ): [UInt8] { 123 return InternalEVM.call( 124 from: self.addressBytes, 125 to: to.bytes, 126 data: data, 127 gasLimit: gasLimit, 128 value: value.flow 129 ) 130 } 131 } 132 133 /// Creates a new bridged account 134 access(all) 135 fun createBridgedAccount(): @BridgedAccount { 136 return <-create BridgedAccount( 137 addressBytes: InternalEVM.createBridgedAccount() 138 ) 139 } 140 141 /// Runs an a RLP-encoded EVM transaction, deducts the gas fees, 142 /// and deposits the gas fees into the provided coinbase address. 143 /// 144 /// Returns true if the transaction was successful, 145 /// and returns false otherwise 146 access(all) 147 fun run(tx: [UInt8], coinbase: EVMAddress) { 148 InternalEVM.run(tx: tx, coinbase: coinbase.bytes) 149 } 150 151 access(all) 152 fun encodeABI(_ values: [AnyStruct]): [UInt8] { 153 return InternalEVM.encodeABI(values) 154 } 155 156 access(all) 157 fun decodeABI(types: [Type], data: [UInt8]): [AnyStruct] { 158 return InternalEVM.decodeABI(types: types, data: data) 159 } 160 161 access(all) 162 fun encodeABIWithSignature( 163 _ signature: String, 164 _ values: [AnyStruct] 165 ): [UInt8] { 166 let methodID = HashAlgorithm.KECCAK_256.hash( 167 signature.utf8 168 ).slice(from: 0, upTo: 4) 169 let arguments = InternalEVM.encodeABI(values) 170 171 return methodID.concat(arguments) 172 } 173 174 access(all) 175 fun decodeABIWithSignature( 176 _ signature: String, 177 types: [Type], 178 data: [UInt8] 179 ): [AnyStruct] { 180 let methodID = HashAlgorithm.KECCAK_256.hash( 181 signature.utf8 182 ).slice(from: 0, upTo: 4) 183 184 for byte in methodID { 185 if byte != data.removeFirst() { 186 panic("signature mismatch") 187 } 188 } 189 190 return InternalEVM.decodeABI(types: types, data: data) 191 } 192 }