npm install ganache-cli web3 solc@0.8.18
# solc 최신 버전이 호환되지 않아 0.8.18버전을 사용
class.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Counter {
uint256 value;
constructor(){}
// setter, send
function setValue(uint256 _value) public {
value = _value;
}
// getter, call
function getValue() public view returns(uint256) {
return value;
}
}
npx solc --bin --abi ./class.sol
컴파일 진행 후 bin 파일과 abi 파일이 생성됨
bin 파일은 스마트 컨트랙트 배포를 할 때 EVM에 등록할 코드를 byte code로 컴파일 한 내용을 담고 있음
608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063209652551461003b5780635524107714610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea264697066735822122029da9ba8ae64ae66cf30162ed11840a712d312aacb68f399c38268fd324bda4764736f6c63430008120033
abi 파일은 스마트 컨트랙트 안에 존재하는 함수와 매개변수들을 json 형식으로 나타낸 리스트를 담고 있음
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"getValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Transaction 생성
npx gaanche-cli -h 0.0.0.0
const Web3 = require("web3")
const web3 = new Web3("http://127.0.0.1:8545")
const tx = web3.eth.sendTransaction({
from: "0x697Cf8433AA77C66913c0eA4F6188d5Cf72e23aD", // EOA
gas: "500000",
data: "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063209652551461003b5780635524107714610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea264697066735822122029da9ba8ae64ae66cf30162ed11840a712d312aacb68f399c38268fd324bda4764736f6c63430008120033", // bin 파일 내용 앞에 0x를 붙여줘서 hex값이라는 걸 명시해줌
})
web3.eth.sendTransaction(tx).then(console.log) // 트랜잭션을 발생시켜 이더리움 네트워크에 코드를 등록한다.
배포가 완료되면 리턴값에서 ContractAddress를 얻을 수 있다. (CA)
ContractAddress를 이용해 스마트 컨트랙트 코드에 접근이 가능하다.
const Web3 = require("web3")
const web3 = new Web3("http://127.0.0.1:8545")
const abi = [
{ inputs: [], stateMutability: "nonpayable", type: "constructor" },
{
inputs: [],
name: "getValue",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function",
},
{
inputs: [{ internalType: "uint256", name: "_value", type: "uint256" }],
name: "setValue",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
]
// 호출은 제3자가 가능하지면 실행하는 건 EVM이 실행하기 때문에 EVM이 알 수 있도록 HEX값으로 변환해줘야 한다.
const dataCodeCall = web3.eth.abi.encodeFunctionCall(
{
inputs: [],
name: "getValue",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function",
},
[]
)
console.log(dataCodeCall) // 0x20965255
// Call은 Gas가 발생하지 않기 때문에 From을 명시하지 않아도 된다.
// 실행되도 블럭이 생성되지 않는다.
web3.eth
.call({
to: "0x6B1E5EA334e1fc5feA3cE97837C858e41C23C742", // 실행할 CA
data: dataCodeCall,
})
.then(console.log)
const dataCodeSend = web3.eth.abi.encodeFunctionCall(
{
inputs: [{ internalType: "uint256", name: "_value", type: "uint256" }],
name: "setValue",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
[10]
)
// setValue 메서드에 매개변수가 들어가기 때문에 두 번째 인자에 내용을 넣어줘야 한다.
console.log(dataCodeSend)
// 0x55241077000000000000000000000000000000000000000000000000000000000000000a
// Send는 Gas가 발생하기 때문에 From을 명시해줘야 한다.
// 실행이 되면 Transaction Pool에 Pending되어 있다 Mining이 될때 블록에 들어가면서 값이 변경이된다.
const tx = {
from: "0xb7253b719a20593D75d00abbf4ee1f8B1328EAAB", // Gas를 지불할 EOA
to: "0x6B1E5EA334e1fc5feA3cE97837C858e41C23C742", // 실행할 CA
data: dataCodeSend,
gas: "50000",
gasPrice: 20000000000,
}
web3.eth.sendTransaction(tx).then(console.log)
JavaScript에서 getter와 같이 자신의 상태 변수를 가져오는 메서드를 호출하는 것은 call
이라고 부른다.
call
은 단순히 자신의 상태 변수를 가져오기만 하기 때문에 블록을 생성하지 않고 블록을 생성하지 않기 때문에 Gas 비용이 들지 않는다.
Solidity
문법에서 getter를 표현할 수 있는 예약어로 view
가 존재하는데 이 예약어가 적힌 메서드는 Gas 비용이 들지 않는다고 보면 된다.
JavaScript에서 setter와 같이 값을 변경하는 메서드를 호출하는 것은 send
라고 한다.
send
는 변경된 내용이 반영되려면 블록에 저장되야 하기 때문에 Mining
이 필요하고 변경 과정에서 연산이 필요하기때문에 Gas 비용이 부과된다.