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 비용이 부과된다.