'solidity'에 해당되는 글 3건

  1. 2018.11.06 Truffle Test array 예제
  2. 2018.07.15 Ethereum dApp - Dev Environment
  3. 2018.06.12 Solidity nested Mapping

간단하게 array를 세팅하는 solidity코드 및 테스트코드 예제입니다. (제가 작성한 건 아니지만..^^)

사전환경: $ganache-cli   ( -l 1000000000 -p 7545)  

               /migrations밑에 2_deploy_contracts.js에 TestArray.sol 추가. 


실행방법: $truffle compile -> $truffle migrate -> $truffle test  

  혹은

          $truffle develop

          $migrate

          $test (test/testarray.test.js)


      $truffle network 하면 deploy된 address를 볼 수 있음.

Solidity 소스:

pragma solidity ^0.4.24;

contract TestArray {

uint[] heroArray;

constructor() public {

}

function setHeroArray(uint[] array) public {
for (uint i=0 ; i < array.length; i++) {
setValue(array[i]);
}
}

function setValue(uint a) private {
heroArray.push(a);
}

function getHeroArray(uint a) view public returns(uint[]) {
return heroArray;
}

}


test/testarray.test.js 소스:

const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const json = require('./../build/contracts/TestArray.json');

let accounts;
let arraySC;
const interface = json['abi'];
const bytecode = json['bytecode'];

beforeEach(async() => {
accounts = await web3.eth.getAccounts();
arraySC = await new web3.eth.Contract(interface)
.deploy({data: bytecode})
.send({from: accounts[0], gasLimit: 4000000});
});

describe(' --- Test Array --- ', () => {
it('array Set', async() => {
await arraySC.methods.setHeroArray([3,3,4]).send({from: accounts[0], gasLimit:150000});

let resultArray = await arraySC.methods.getHeroArray(1).call();

console.log('resultArray : ', resultArray);
assert.equal(resultArray[2], 4, "값이 제대로 세팅되지 않았습니다 ");
});
});


Posted by yongary
,

제목: truffle과 ES6 javascript를 이용한, 이더리움 dApp 개발환경 : 



Explanation - ENG

  • BaseContract (below) is base class when making javascript Contract using truffle & ES6-javascript
  • This can be used when using several ES6-javascript like Vue.js, Angular.js and react.js
  • When developing Ethereum dApp, this class helps to map functions between Solidity and Javascript, and helps web3 process of MetaMask and etc.
  • Detail using example can be found on https://github.com/yongarykim/RSTdAppDevEnv/tree/master/react-frontend/src/contracts


Explanation - KOR

  • truffle을 이용해서 javascript contract를 개발할 때, 상속받아서 쓰도록 만든 기본 class이다.
  • 각종 ES6-javascript language에서 아래 BaseContract를 상속을 받아서 이더리움 dApp개발시 사용할 수 있다.
  • 이더리움 dApp개발시 간단히 solidity의 함수와 js 함수간 매핑하도록 도와주며, metaMask 등의 web3처리를 자동으로 해준다. 자세한 사용예제는 https://github.com/yongarykim/RSTdAppDevEnv/tree/master/react-frontend/src/contracts 를 참고하도록 한다.


소스:  https://github.com/yongarykim/ES6-ContractBase


/**
* BaseContract - super class of all contracts (using Web3 & TruffleContract)
*
* <History>
* @author Yong Kim (yongary.kim@gmail.com)
* @date 2018.4.5 - first created
* @date 2018.6.11 - promisify & getMyAccount added
* @date 2018.6.13 - contractDeployed added.
*
*/

import Web3 from 'web3';
import TruffleContract from 'truffle-contract';
import $ from 'jquery';
import { Subject } from 'await-notify';

//web3함수를 Promise로 만들기 위한 공통모듈
const promisify = (inner) =>
new Promise((resolve, reject) =>
inner((err, res) => {
if (err) { reject(err) }
resolve(res);
})
);

export default class BaseContract {

constructor() {
this.contract = {};
this.initWeb3();
//contract.deployed()가 initContract 보다 빨리 호출되는 경우용
this.eventWaiting = new Subject();
}

initWeb3() {
// Metamask
console.log("this.web3:")
console.log(this.web3);
console.log("window.web3:")
console.log(window.web3);

if (typeof window.web3 !== 'undefined') {
this.web3 = new Web3(window.web3.currentProvider);
} else {
//LocalTest set the provider you want from Web3.providers
console.log("initWeb3: local");
this.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:7545"));
}
console.log(this.web3);
}

/* new 이후에 호출 필요 */
initContract(contractJson) {

let self = this;
$.getJSON(contractJson, function (data) {
// Get the necessary contract artifact file and instantiate it with truffle-contract
let contractArtifact = data;

console.log('initContract:' + self.contract);

self.contract = TruffleContract(contractArtifact);
self.contract.setProvider(self.web3.currentProvider);

console.log('initContract out');
self.eventWaiting.notify(); //contractDeployed가 먼저 불렸을 경우 대비.
});
}

/* contract관련 check함수 */

/**
* contractDeployed
* - same as contract.deployed,
* But waiting initContract to finish
* - useful when doing something on screen loading..
* */
contractDeployed = async () => {

console.log('in contractDeployed:');
if (Object.keys(this.contract).length === 0 ) {//contract Empty = initContract수행중
console.log(this.contract);

while (true) {
await this.eventWaiting.wait();
console.log('initContract Done');
break; //exit when notified.
}
}
console.log('out contractDeployed:');
return this.contract.deployed().then((instance) => {return instance;});

}


/* web3/eth Basic함수들 - eth의 sync함수는 값을 못 읽어 오는 경우가 발생가능하므로 async함수를 써야 함. */

getMyAccount = async () => {
const accounts = await promisify(cb => this.web3.eth.getAccounts(cb));
return accounts[0]; //accounts Array의 0번째가 본인 account임.
}
}



부연설명


이더리움 dApp을 개발할 경우, truffle과 javascript를 이용해서 개발하는 게 편리하다.

특히, javascript를 ES6로 사용하면 상속을 쉽게 사용할 수 있기 때문에,

복잡한 dApp을 개발할 수 있는  밑거름이 된다. 

(아무 생각없이, html과 javascript, truffle을 섞어서 쓴다면 간단한 dApp을 만들고 나서

복잡한 dApp은 만들다가 포기하게 될 확률이 높아진다)

 

복잡하고 어려운 dApp을 개발하기 위해서는 건물의 기초공사부터 튼튼하게 해 놓듯이

ES6 javascript를 이용해서 javascript를 개발하기를 권장하고.

그래서, 그 때 도움이 될 class를 만들어 본것이다.


ES6- javascript의 상속을 사용할 수 있기 때문에 쉽게쉽게 truffle contract기반의

javascript contract가 생성이 가능하다. 


자세한 사용예제는  https://github.com/yongarykim/RSTdAppDevEnv/tree/master/react-frontend/src/contracts 



Posted by yongary
,

solidity개발시 gas비용을 최소화하기 위해 연산을 줄이는 것이 중요하다.


그래서 가장 유용한 data Type은 mapping인데,

mapping안에 array를 넣는 방법도 꽤 추천할 만하지만


array의 길이가 길어진다면 O(n)의 서칭이 발생하므로,

데이타가 많다면 mapping안에 mapping을 또 넣는 방법이 좋을 것 같다.


일반적인 language용어로 말하자면, 

hashMap안에 또 hashMap을 넣는 것이다.


단, 이를 조회하려면 parentKey와 childKey모두 알아야 조회가 가능하다.


예제는 다음과 같다. 참고사이트: REF


contract SampleContract {

  struct ChildStruct {
    bool isPresent;
    bytes32 name;
  }

  struct ParentStruct {
    bool isPresent;
    bytes32 name;
    mapping (bytes32 => ChildStruct) childStructs; 
  }

  mapping(bytes32 => ParentStruct) public parentStructs;

  function insertData(
    bytes32 parentKey, 
    bytes32 parentName, 
    bytes32 childKey, 
    bytes32 childName)
    public 
    returns(bool success)
  {

    parentStructs[parentKey].isPresent = true;
    parentStructs[parentKey].name = parentName;
    parentStructs[parentKey].childStructs[childKey].isPresent = true;
    parentStructs[parentKey].childStructs[childKey].name = childName;
    return true;
  }

  function getChild(bytes32 parentKey, bytes32 childKey) public constant returns(bool isPresent, bytes32 name) {
    return (parentStructs[parentKey].childStructs[childKey].isPresent, parentStructs[parentKey].childStructs[childKey].name);
  }

}


Posted by yongary
,