[TOC]
EtherEaseWithFMZ 자습서
FMZ를 사용하여 쉽게 이더리움에 기반한 web3 개발을 시작하십시오
이더리움 (Ethereum) 은 블록체인 기술을 기반으로 하는 스마트 컨트랙트 플랫폼으로, 스마트 컨트랙트를 작성하고 배포할 수 있는 분산된 방법을 제공한다. 스마트 컨트랙트는 블록체인에서 자동으로 실행되고, 타인을 신뢰하지 않고 다양한 비즈니스 로직을 구현할 수 있는 특별한 유형의 컴퓨터 프로그램이다.
FMZ 양자 거래 플랫폼 (FMZ.COM이더리움 블록체인 (ETH) 은 개발자가 이더리움 블록체인과 생태계와 더 쉽게 상호 작용할 수 있도록 사용하기 쉬운 API를 제공합니다. 이더리움 블록체인은 분산 거래소 (DEX) 에 액세스하고, 체인 데이터 획득, 트랜잭션 전송 및 기타 기능을 달성합니다.
이 튜토리얼에서 예제들은JavaScript
언어, 테스트 환경은 둘 다 사용합니다이더리움 메인 네트워크그리고괴르리 시험망. 그리고 당신은 또한 FMZ 플랫폼의 API 문헌에서 튜토리얼에서 사용되는 API 인터페이스와 관련 설명, 코드 예제를 볼 수 있습니다.
FMZ 퀀트 트레이딩 플랫폼을 사용하는 법을 배우기 전에 몇 가지 기본 개념에 익숙해질 필요가 있습니다.
FMZ 양자 거래 플랫폼 공식 웹사이트에 등록하고 로그인 한 후 (https://www.fmz.com), 당신은 플랫폼의 다양한 기능을 사용할 수 있습니다. FMZ 웹 사이트는 전체 시스템의 관리 끝이며 사용자가 작성한 프로그램이 실제로 도커에서 실행됩니다. 도커 소프트웨어 프로그램은 서버, 컴퓨터 등과 같은 다양한 장치에 배포 될 수 있습니다. 사용자가 프로그램을 작성하고 FMZ 웹 사이트에서 실행 인스턴스를 만들 때 FMZ 플랫폼은 도커와 통신하여 프로그램 인스턴스를 시작합니다.
프로그램 인스턴스를 실행하려면 도커를 배포해야합니다. 도커의 배포 또한 매우 간단하며 플랫폼에 배포 설명서가 있습니다. FMZ에서 제공하는
서버, 개인용 컴퓨터 및 기타 장치에 도커 프로그램을 배포하고 실행할 수 있습니다. 네트워크가 정상인 한 (특정 교환 인터페이스, 노드 주소 등과 같은 해당 목표물에 액세스 할 수 있어야 합니다.) 배포의 주요 단계는 다음과 같습니다.
robot
. 각 FMZ 계정에 고유 한 도커 통신 주소를 구성, FMZ에 로그인 한 후, 당신은 자신의 주소를 볼 수 있습니다https://www.fmz.com/m/add-node
페이지 (즉,./robot -s node.fmz.com/xxxxx
이 주소의 문자열에서xxxxx
위치는 각 FMZ 계정에 따라 다릅니다.) 마지막으로, FMZ 계정의 암호를 입력해야합니다. 이러한 설정을 구성 한 후, 도커 프로그램을 실행하십시오.FMZ 플랫폼
FMZ 플랫폼에 도커 페이지를 추가, 주소:https://www.fmz.com/m/add-node
FMZ 퀀트 트레이딩 플랫폼은 지원하는 무료 디버깅 도구를 제공합니다.JavaScript
, TypeScript
, 그리고 페이지는:https://www.fmz.com/m/debug. 실행할 인스턴스를 생성하는 것은 청구되기 때문입니다. 초기 학습 기간 동안, 테스트와 학습을 위해 이 디버깅 도구를 사용할 수 있습니다. 최대 실행 시간 제한 3 분을 제외하고, 디버깅 도구를 사용 하 여 실행할 인스턴스를 생성 하는 것 사이에는 차이가 없습니다.
이 약물을 사용할 때TypeScript
언어, 당신은 작성해야합니다// @ts-check
첫 번째 코드 줄에서TypeScript
모드; 만약 전환되지 않은 경우, 기본은JavaScript
language.
FMZ에서
FMZ 플랫폼에 로그인 상태에서,https://www.fmz.com/m/add-platform
이 페이지에서는 교환 정보를 구성할 수 있습니다. 교환은 일반적인 개념입니다.
선택Web3
, RPC 노드 주소를 구성, 개인 키를 구성, 당신은 오른쪽 아래쪽 구석에 클릭 할 수 있습니다
노드는 자체 제작된 노드 또는 노드 서비스 제공자가 제공하는 노드일 수 있다.인푸라. 등록 후, 당신은 자신의 계정의 노드 주소를 볼 수 있습니다. 마인넷과 테스트넷은 모두 사용 가능, 매우 편리합니다.Rpc Address
위의 그림에서 보이는 제어 장치입니다. 라벨은 구성된 교환 객체를 구별하기 위해 스스로 이름을 지정할 수 있습니다.
사진에서,https://mainnet.infura.io/v3/xxxxxxxxxxxxx
개인 Infura ETH 메인 네트워크 RPC 노드 주소입니다.
도커 프로그램을 배포하고 교환 객체를 구성 한 후, 당신은 사용할 수 있습니다FMZ.COM테스트를 위한
우리는 몇 가지 간단한 예를 나열합니다. 기본부터 시작합니다. 다양한 언어와 도구에 대해, 그림에서 보이는 것처럼 web3에 액세스 할 수있는 방법이 있습니다:
FMZ에서, RPC 메소드 호출도 캡슐화되고, 이 함수들은 FMZ API 함수에서 캡슐화된다.exchange.IO
전화 방식은exchange.IO("api", "eth", ...)
첫 번째 매개 변수는"api"
, 두 번째 매개 변수는"eth"
, 그리고 다른 매개 변수는 호출되는 특정 RPC 방법에 달려 있습니다.
출력 정보를 위해, 우리는Log
FMZ 플랫폼의 기능Log
이 함수는 여러 매개 변수를 받아들여 FMZ 플랫폼의
이eth_getBalance
이더리움의 메소드는 이더리움에 있는 주소의 ETH 잔액을 쿼리하는 데 사용되며 이 메소드는 두 개의 매개 변수를 필요로 합니다.
Vitalik Buterin
ETH 지갑 주소는, 알려진 주소는0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
.function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
}
이미 도커를 배포 (그림: linux/amd64...) 및 교환 객체를 구성 (그림: Web3 테스트), 디버깅 도구에서 테스트 코드:
코드를 실행하고 결과를 표시하기 위해
eth평형: 0x117296558f185bbc4c6
이log
함수는ethBalance
변수 값:0x117296558f185bbc4c6
, 문자열 유형입니다.ETH 잔액의 열여섯 소수 값안쪽wei
단위,1e18 wei
1과 같다는 것입니다ETH
따라서, 그것은 읽을 수 있는 소수 ETH 잔액으로 전환되어야 합니다.
전환ethBalance
읽기 쉬운 데이터로:
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
// Converting ethBalance into readable data
let vitalikEthBalance = parseInt(ethBalance.substring(2), 16) / 1e18
Log("vitalikEthBalance:", vitalikEthBalance)
}
계속 검색하세요https://etherscan.io/
:
그러나 언어 자체의 정확성 문제로 인해 이러한 처리 방식에 오차가 발생할 수 있습니다. 따라서 FMZ 플랫폼은 데이터 처리를 위해 두 가지 기능을 내장했습니다.
코드를 다시 조정하세요.
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
// The precision unit of ETH is 1e18
let ethDecimal = 18
Log("vitalikEthBalance:", Number((BigDecimal(BigInt(ethBalance)) / BigDecimal(Math.pow(10, ethDecimal))).toString()))
}
비탈릭 에스 밸런스: 5149.6244846875215
eth_chainId
그리고net_version
이 두 함수는 현재 RPC 노드가 연결된 블록 체인의 Id를 반환합니다.net_version
소수점 Id를 반환하고eth_chainId
hexadecimal id를 반환합니다.
ChainId에 대응하는 네트워크 이름
1 - ethereum mainnet
2 - morden testnet (deprecated)
3 - ropsten testnet
4 - rinkeby testnet
5 - goerli testnet
11155111 - sepolia testnet
10 - optimism mainnet
69 - optimism kovan testnet
42 - kovan testnet
137 - matic/polygon mainnet
80001 - matic/polygon mumbai testnet
250 - fantom mainnet
100 - xdai mainnet
56 - bsc mainnet
구성된 이더리움 테스트넷으로 테스트goerli
노드:
function main() {
let netVersionId = exchange.IO("api", "eth", "net_version")
let ethChainId = exchange.IO("api", "eth", "eth_chainId")
Log("netVersionId:", netVersionId)
Log("ethChainId:", ethChainId, " , conversion:", parseInt(ethChainId.substring(2), 16))
}
전화해eth_gasPrice
현재를 검색하는 방법gas price
사슬에
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
Log("gasPrice:", gasPrice, " , conversion:", toAmount(gasPrice, 0))
}
여기 우리는 열여섯진열을 읽을 수 있는 수치 값으로 변환하는 함수를 작성합니다.toAmount
또한,gasPrice
이wei
, 그래서 공식 매개 변수에 대응하는 실제 매개 변수에 값 0을 전달decimals
.
"eth_blockNumber
블록 높이를 검색하는 데 사용됩니다.
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log(toAmount(blockNumber, 0))
}
디버깅 도구 실행:
계속 검색하세요https://etherscan.io/
:
블록 정보를 검색합니다.
function main() {
let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log(blockNumber)
let blockMsg = exchange.IO("api", "eth", "eth_getBlockByNumber", blockNumber, true)
Log(typeof(blockMsg), blockMsg)
// Due to the excessive content of Log output, it will be truncated automatically, so traverse each field of the returned block information and print them one by one
for (let key in blockMsg) {
Log("key:", key, ", val:", blockMsg[key])
}
}
많은 스마트 컨트랙트 애플리케이션이 이더리움에서 실행됩니다.ENS
그 중 한 명입니다.ENS
이더리움 네임 서비스 (Ethereum Name Service) 는 이더리움 블록체인을 기반으로 한 분산된 도메인 이름 해결 서비스입니다.
이더리움 창업자 비탈릭 부테린의 지갑의 잔액을 확인한 튜토리얼의 예를 기억하시나요?0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
그럼 어떻게 주소를 알 수 있을까요? 사실,ENS
직관적인 이름을 사용하는 스마트 계약vitalik.eth
.
이 장의 다음 내용은 에테리움 메인넷 환경을 사용 합니다.ENS
서류,Hashing Names
이더리움 도메인 이름을 검색하는 데 필요합니다.vitalik.eth
.
function nameHash(name) {
if (name == "") {
return "0000000000000000000000000000000000000000000000000000000000000000"
} else {
let arr = name.split(".")
let label = arr[0]
arr.shift()
let remainder = arr.join(".")
return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
}
}
위의 코드 예제에서, 우리는 또 다른 익숙하지 않은 함수를 보았다Encode
이 함수는 FMZ 플랫폼의 API 함수이며 FMZ 플랫폼에서 연산을 암호화하는 데 특별히 사용됩니다. 이 함수는 여러 암호화 방법과 다양한 해시 알고리즘을 지원합니다.
Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)
ENS 문서의 설명에 따르면sha3.keccak256
데이터를 처리하는 알고리즘
전화해nameHash
기능, 예를 들어:Log(nameHash("vitalik.eth"))
, 당신은 얻을 수 있습니다:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835
, 그리고 0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835
가변으로 사용 됩니다.resolver
ENS 스마트 컨트랙트에서
let ensNode = "0x" + nameHash("vitalik.eth") // Prepare the parameters ensNode for calling the resolver method
ENS 문서에 따르면 ENS 스마트 계약 애플리케이션의 계약 주소는 다음과 같습니다.0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
전화하기 전에resolver
스마트 계약의 방법, 우리는 또한 준비해야합니다ABI
계약의
이 사실을 알게 되면, 여러분은 질문할 수 있습니다.ABI
똑똑한 계약의?
ABI, or Application Binary Interface, is the interface standard for smart contracts to communicate with the external world.
The ABI of a smart contract defines the contract's function interfaces, parameter types, return values, and other information, as well as specifications for calling the contract and passing parameters.
The ABI of a smart contract is usually stored in JSON format and contains the following information:
Contract function interfaces: function names, parameter lists, return values, etc.
Function parameter types: such as uint256, bool, string etc.
Encoding methods for input and output parameters of functions: Smart contracts use an encoding method called Solidity ABI to encode input and output parameters of functions so that they can interact with Ethereum network.
In Ethereum network ,the ABI of a smart contract is used to call its functions. When you need to call a contract function, you need to provide the name of the function, its parameters, and bytecode encoded according to ABI encoding method.
Ethereum nodes will package this information into transactions and send them out on Ethereum network for execution.
In Solidity language,the keyword 'interface' can be used define ABIs for smart contracts. Ethereum development tools like Remix IDE ,Truffle also provide editing & generation tools making it easier developers create & use ABIs.
추출resolver
ENShttps://etherscan.io/
또는 다른 채널 (예를 들어 관련 프로젝트 문서) 을 통해 ABI를 얻습니다.
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
여기서 우리는 FMZ 플랫폼에서 새로운 호출 방법을 배울 것입니다.exchange.IO("abi", address, abiContent)
, ABI 등록에 사용 됩니다.address
매개 변수는 스마트 계약 주소와abiContent
매개 변수는 해당 스마트 계약 ABI (string) 입니다.
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver) // 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e is the address of the ENS smart contract deployed on the Ethereum mainnet
다음으로, 당신은resolver
ENS 스마트 계약의 메소드,ENS: Public Resolver
contract.
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
사용ENS: Public Resolver
계약서addr
비탈릭 부테린의 지갑 주소를 얻기 위한 방법ENS: Public Resolver
이 스마트 계약에 대한 ABI 정보는 여전히https://etherscan.io/
.
let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)
마지막으로,ENS: Public Resolver
계약서addr
매개 변수가 여전히ensNode
.
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
로그 함수 출력:
vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045
function nameHash(name) {
if (name == "") {
return "0000000000000000000000000000000000000000000000000000000000000000"
} else {
let arr = name.split(".")
let label = arr[0]
arr.shift()
let remainder = arr.join(".")
return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
}
}
function main() {
// Calculate the name
let ensNode = "0x" + nameHash("vitalik.eth")
// Register ENS contract
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver)
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
// Register ENS Public Resolver contract
let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
}
이전 코스 장에서, 우리는 개인 키를 구성하는 방법을 배웠습니다. 어떻게 우리는 구성 교환 객체에 대한이 개인 키에 대응하는 지갑 주소를 알고 있습니까? FMZ에서, 당신은exchange.IO("address")
설정된 개인 키에 해당하는 지갑 주소를 얻는 기능입니다.
이 장의 다음 컨텐츠는 Goerli 테스트넷 환경을 사용합니다. 그래서 제가 사용하는 노드는:https://goerli.infura.io/v3/*******
, 그리고 Infura는 각 등록된 사용자에 대해 다른 노드 주소를 할당합니다.*******
특정 콘텐츠를 숨깁니다.
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
}
지갑 주소를 알고 나면 Ethereum의 RPC 방법을 사용할 수 있습니다.eth_getTransactionCount
지갑 주소의 트랜잭션 수를 쿼리합니다. 이더리움에서는 이 수치가 매우 일반적입니다.nonce
이더리움 (Ethereum) 에서 nonce는 각 트랜잭션이 고유하다는 것을 보장하기 위해 사용되는 고유 번호입니다. 이것은 증가하는 숫자이며 새로운 트랜잭션이 전송될 때마다 자동으로 증가합니다. 따라서, 스마트 계약에 트랜잭션을 보낼 때 트랜잭션이 독특하고 올바른 순서로 있는지 확인하기 위해 nonce를 제공해야합니다. 우리는이 정보를 일부 자료와 문서에서 찾을 수 있습니다.
여기,PendingNonceAt
Go 언어의 이더리움 라이브러리의 함수는 실제로eth_getTransactionCount
이전 강의에서 우리는 또한 RPC 방법을 호출하는 방법을 배웠습니다. 여기 우리는exchange.IO("api", "eth", ...)
다시 작동합니다.
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
/**
* eth_getTransactionCount
* @param address - string - The address from which the transaction count to be checked.
* @param blockNumber - string - The block number as a string in hexadecimal format or tags.
* @returns The integer of the number of transactions sent from an address encoded as hexadecimal.
*/
let nonce: string = exchange.IO("api", "eth", "eth_getTransactionCount", walletAddress, "pending")
Log("wallet address:", walletAddress, "current nonce:", nonce, ", convert to decimal:", toAmount(nonce, 0))
}
이 트랜스퍼레이션 작업을 설명하기 전에 몇 가지 개념을 간략하게 이해해 보겠습니다. 이더리움에서 이더리움 토큰을 전송할 때 일정량의 ETH 토큰이 소비됩니다 (가스 수수료로). 가스 수수료는 두 가지 매개 변수에 의해 결정됩니다:
가스 가격
그러나 이더리움 네트워크의 가스 수수료는 시장 수요와 사용자가 기꺼이 지불하는 수수료에 따라 항상 변동하므로 코드에서 고정된 가스 수수료를 작성하는 것은 때로는 이상적인 선택이 아닙니다.eth_gasPrice
우리가 전에 배운 방법, 평균 가스 가격을 얻을 수 있습니다.
가스 제한
표준 이더 전송은 21,000 유닛의 가스 한계를 가지고 있습니다.
그 개념들을 이해한 후nonce
, gasPrice
, 그리고gasLimit
, 당신은 전송을 테스트 할 수 있습니다. FMZ는 매우 간단하고 사용하기 쉬운 전송 기능을 제공합니다.
exchange.IO("api", "eth", "send", toAddress, toAmount)
전송에 사용되면, 세 번째 매개 변수exchange.IO
toAddress
매개 변수는 전송 중에 ETH를 받는 주소입니다.toAmount
ETH의 양입니다.
매개 변수nonce
, gasPrice
, 그리고gasLimit
모두 FMZ에서 자동으로 얻은 시스템 기본 값을 사용할 수 있습니다. 또한 지정할 수 있습니다:
exchange.IO("api", "eth", "send", toAddress, toAmount, {gasPrice: 5000000000, gasLimit: 21000, nonce: 100})
다음으로, 우리는 특정 양의 ETH를 Goerli 테스트 네트워크의 특정 주소로 전송합니다.
function toInnerAmount(s, decimals) {
return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
let ret = exchange.IO("api", "eth", "send", "0x4D75a08E870674E68cAE611f329A27f446A66813", toInnerAmount(0.01, 18))
return ret // return Transaction Hash : 0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
}
이더리움 전송 금액의 단위는wei
, 사용자 정의 함수toInnerAmount
이 값의 처리에 사용되어야 합니다wei
units.
쿼리 트랜잭션 해시:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
에https://etherscan.io/
.
당신은 또한 쿼리 전송 해시에 코드를 작성할 수 있습니다0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
,eth_getTransactionReceipt
질의 방법.
function main() {
let transHash = "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e"
let info = exchange.IO("api", "eth", "eth_getTransactionReceipt", transHash)
return info
}
쿼리 결과:
{
"cumulativeGasUsed": "0x200850",
"effectiveGasPrice": "0x1748774421",
"transactionHash": "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e",
"type": "0x0",
"blockHash": "0x6bdde8b0f0453ecd24eecf7c634d65306f05511e0e8f09f9ed3f59eee2d06ac7",
"contractAddress": null,
"blockNumber": "0x868a50",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasUsed": "0x5208",
"to": "0x4d75a08e870674e68cae611f329a27f446a66813",
"status": "0x1",
"transactionIndex": "0x23",
"from": "0x6b3f11d807809b0b1e5e3243df04a280d9f94bf4",
"logs": []
}
각 필드에 대응하는 설명:
blockHash - The hash value of the block where the transaction is located.
blockNumber - The block number of the block where the transaction is located, encoded in hexadecimal.
contractAddress - If it's a contract creation, the address of the contract; otherwise null.
cumulativeGasUsed - The total gas used when executing this transaction in the block.
effectiveGasPrice - Total base fee plus tip per unit of gas.
from - Sender's address.
gasUsed - Gas used by this specific transaction.
logs - Array of log objects generated by this transaction.
address - Address that generated this log.
topics - Data array with 0 to 4 indexed log parameters, each with 32 bytes. In Solidity, first topic is event signature hash (e.g., Deposit(address,bytes32,uint256)), unless you declare an event using anonymous specifier.
data - Non-indexed parameters for logs with length of 32 bytes.
blockNumber - The block number of the block where this log is located.
transactionHash - Transaction hash at time when log was created. Null if pending state.
transactionIndex - Index position during creation. Null if pending state.
blockHash - The hash value for containing block.
logIndex - Hexadecimal-encoded integer index position within containing block. Null if pending state.
removed - True if deleted due to chain reorganization; false for valid logs.
logsBloom - Bloom filter for retrieving related logs.
status - Hexadecimal-encoded value either being '1' (success) or '0' (failure).
to - Receiving party's address; null for contract creation transactions.
transactionHash - The hash value associated with given transaction.
transactionIndex - Hexadecimal-encoded index position within its respective containing-block.
type - Type value.
Read
방법, 그리고 이러한 방법을 호출하는 것은 필요하지 않습니다gas
이 장에서는 몇 가지Write
이더리움에 스마트 계약의 방법과 지불gas
이 작업은 네트워크 전체의 모든 노드와 마이너에 의해 확인되고 블록체인 상태를 변경합니다.
ERC20 계약 (ERC20 토큰 계약) 에 대해 FMZ 플랫폼은 ERC20 계약 ABI의 ABI를 시스템으로 직접 구축된 일반적인 ABI로 나열하고, ABI 등록의 단계를 제거합니다. 우리는 또한 ENS 계약 방법을 호출하기 전에 ENS 계약을 ABI로 등록했을 때 이전 튜토리얼에서 ABI에 대해 배웠습니다.
ABI를 더 잘 이해하기 위해, 사용 전에 확인 할 수 있습니다. 여기 ERC20 계약에 대한 ABI입니다:
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"tran