- library를 사용하면 modular, reusable elegant한 contract를 짤 수 있다.
- standard library가 아직 개발되지 않았다.
- deployed contract는 업그레이드할 수 없다.
- EVM 외부에서 data를 가져올 수 없다. 이는 Oracle을 포함하는 트랜잭션을 날려야만 가능하다.
- library는 contract와는 다른 type이다.
- library는 storage를 가지지 않지만 library와 link되어 있는 contract의 storage를 수정할 수 있다.
- library는 ether를 가지지 않는다. library는 payable function을 사용할 수 없고, fallback function을 사용할 수 없다. 이는 compile 단계에서 체크된다.
- library는 piece of code로서 library를 다시 배포할 필요없이 어느 contract이던 상관없이 호출할 수 있다.
- library를 사용하면 gas를 줄일 수 있으며 blockchain을 오염시키지 않는다. 오염시킨다는 의미는 contract를 업그레이드할 때 똑같은 코드(업데이트 되지 않은 코드)가 또 블록체인 위에 업데이트되기 때문에 오염시킨다고 표현을 함.
- audited code의 library를 사용하면 더욱 secure하다.
- library는 special instruction(
DELEGATECALL
)을 사용한다. library는 마치 contract 그 자체의 코드인 것 처럼 현재 context에서 library를 pass하게 된다."Libraries can be seen as implicit base contracts of the contracts that use them".
library C {
function a() returns (address) {
return address(this);
}
}
contract A {
function a() constant returns (address) {
return C.a();
}
}
C.a() 메소드는 library의 주소가 아닌 contract의 주소를 리턴한다.
- Library linking은 bytecode 레벨에서 이루어진다. contract A가 컴파일되면 0073__C_____________________________________630dbe671f와 같이 placeholder를 둔다. 0dbe671f는 function a()의 signature를 뜻한다. placeholder에는 contract가 연결된 블록체인에 배포된 library의 주소가 들어가게 된다.
- library도 contract와 마찬가지로 bytecode 레벨로 블록체인에 올라가기 때문에 업그레이드 할 수 없다.
- 그러나 Proxy Libraries를 사용해서 이를 해결할 수는 있다.
- library는 storage를 가질 수 없지만 link되어 있는 contract의 storage를 변경시킬 수 있다.
storage
reference가 argument로 library에 전달되면 contract의 상태를 변경시킨다. using
키워드를 사용해서library
안에 있는 함수를 contract안에서 사용할 수 있다.
library CounterLib {
struct Counter { uint i; }
function incremented(Counter storage self) returns (uint) {
return ++self.i;
}
}
contract CounterContract {
using CounterLib for CounterLib.Counter;
CounterLib.Counter counter;
function increment() returns (uint) {
return counter.incremented();
}
}
- library는 event log를 가지지 못한다. 하지만 event를 dispatch할 수 있다.
library EventEmitterLib {
function emit(string s) {
Emit(s);
}
event Emit(string s);
}
contract EventEmitterContract {
using EventEmitterLib for string;
function emit(string s) {
s.emit();
}
event Emit(string s);
}
- library들은 직접적으로 상속은 안되지만 다른 library와 link할 수 있다.